当初、今回は前回 の続きでスキャンした「お講」文書を読解する話の予定だったものの、本連載で以前に紹介した「らじる☆らじる」の録音スクリプト が9月1日から急に動かなくなるという問題が生じたため、予定を変更して「らじる☆らじる」録音スクリプトを改修した話題を紹介することにしました。
「らじる☆らじる」の配信方式
NHKラジオの番組を放送と同時にインターネットでも配信する「らじる☆らじる」については、2011年に始まったころからとりあげてきました 。開始当初、「 らじる☆らじる」は、Adobe Flashplayerを利用する配信方式と共に、Windows Media Playerで再生できる方式(WMA:Window Media Audio)でも配信されていました。
Adobe社が配布しているAdobe Flashplayer(libflash.so)を利用すれば、Linux上のFirefoxからでも「らじる☆らじる」を再生することはできるものの、バイナリでしか配布されないlibflash.soはOSSではありません し、Adobe Flashplayerにはしばしばセキュリティ上の問題 が指摘されます。一方、Adobe FlashをやりとりするRTMP(Real Time Media Protocol)をOSSとして実装したrtmpdump コマンドは、「 らじる☆らじる」の配信が始まった2011年当時、まだ機能や信頼性に欠けていました。
そのため、自作の録音用スクリプトではmplayer経由でWMA形式の音声をダウンロードするような形にしていたものの、「 らじる☆らじる」におけるWMA配信は次第に脇に追いやられ、2015年度から「試行の最終段階」として利用者の聴取状況把握にAdobe Analyticsを使うようになったのに合わせ、目の不自由な人の「読み上げ用」として残されていた配信も8月末で完全に終了 してしまいました。
そう言えば、今年の春ごろからWMA形式での配信には遅延が目立つようになり、録音用スクリプトの待ち時間を増やして調整した記憶があります。今から考えれば、次第にWMA形式の配信用の帯域を絞っていたのかも知れません。
WMA形式での配信が終了してしまったので「らじる☆らじる」の録音を続けるにはスクリプトをAdobe Flashに対応させるしかありません。そこで急遽録音用スクリプトの改修に取りかかりました。
録音用スクリプトの改修
「らじる☆らじる」がどのようなURLで番組を配信しているかは、スマホ用アプリなどが参照するconfig_pc.xml というファイルで定義されています。
config_pc.xml(一部)
<?xml version="1.0" encoding="UTF-8"?>
<radiru_config>
<!-- お知らせ情報テキスト(中身はHTML) -->
<info><![CDATA[/netradio/files/include/oshirase.txt]]></info>
<!-- 各地域のストリームURL -->
<stream_url>
<data>
<areajp>仙台</areajp>
<area>sendai</area>
<apikey>600</apikey>
<r1><![CDATA[rtmpe://netradio-hkr1-flash.nhk.jp/live/NetRadio_HKR1_flash@108442]]></r1>
<r2><![CDATA[rtmpe://netradio-r2-flash.nhk.jp/live/NetRadio_R2_flash@63342]]></r2>
<fm><![CDATA[rtmpe://netradio-hkfm-flash.nhk.jp/live/NetRadio_HKFM_flash@108237]]></fm>
<oshirase><![CDATA[/netradio/files/include/oshirase_sendai.txt]]></oshirase>
<banners><![CDATA[/netradio/files/include/banners_sendai.txt]]></banners>
</data>
<data>
<areajp>東京</areajp>
<area>tokyo</area>
<apikey>001</apikey>
<r1><![CDATA[rtmpe://netradio-r1-flash.nhk.jp/live/NetRadio_R1_flash@63346]]></r1
...
このファイルを見ると、NHK仙台放送局の番組はrtmpe://netradio-hkr1-flash.nhk.jp/live/NetRadio_HKR1_flash@108442
というURLで配信されていることがわかります。
R1がNHKラジオ第一、R2がラジオ第二、FMはNHK FMをそれぞれ示し、NHK仙台放送局のコールサインはJOHKなので、放送局の識別子としてhkを使っているようです。ちなみに名古屋はck、大阪はbkになっています。
とりあえず配信元のURLはわかったものの、そこからデータをどうダウンロードするんだろう、と、rtmpdumpと「らじる☆らじる」をキーワードに検索してみたら、文字通り、「らじる☆らじる」をrtmpdumpで録音する ためのコードを紹介しているページが見つかりました。
このページによると、たとえばNHK FMの配信は
rtmpdump --rtmp "rtmpe://netradio-fm-flash.nhk.jp" \
--playpath 'NetRadio_FM_flash@63343' \
--app "live" \
--swfVfy http://www3.nhk.or.jp/netradio/files/swf/rtmpe.swf \
--live \
-o fm.m4a
という指定でダウンロードできるようです。
指定されているオプションのうち、--swfVfy
は配信されているAdobe Flashを再生するためのプレイヤーの指定 で、「 らじる☆らじる」のソースコードからインクルードされているJavaScript(common.js)の中で指定されているようです。こんなのよく調べたなぁ…、と感心しつつ、この指定を流用させてもらうことにしました。
最近、改めて確認したところ、JavaScriptの名称は"common2015.js"に変更されており、プレイヤーも"rtmpe_ver2015.swf"に変更されていました。もっとも"rtmpe.swf"の指定でもダウンロードはできるので、両者に互換性は持たせてあるようです。
さて、上記のような指定でダウンロードできることがわかれば、後はmplayer経由で録音していた部分をrtmpdump経由に改造するだけです。具体的にはradiru_rec.py のチャンネル定義部分をRTMP経由に書きかえて、
206 if channel == 'r1':
207 rtmp='rtmpe://netradio-r1-flash.nhk.jp'
208 playpath='NetRadio_R1_flash@63346'
209 elif channel == 'r2':
210 rtmp='rtmpe://netradio-r2-flash.nhk.jp'
211 playpath='NetRadio_R2_flash@63342'
212 elif channel == 'fm':
213 rtmp='rtmpe://netradio-fm-flash.nhk.jp'
214 playpath='NetRadio_FM_flash@63343'
215 else:
216 print("channel set error:{0}".format(channel))
217 usage()
218 sys.exit(1)
生成する録音用スクリプトもrtmpdump を使うように修正しました。
229 lines.append('#!/bin/sh')
230 lines.append('flvfile={0}/{1}.flv'.format(musicdir, title))
231 lines.append('m4afile={0}/{1}.m4a'.format(musicdir, title))
232 lines.append('(rtmpdump --rtmp {0} --playpath {1} --app "live" \
--swfVfy "http://www3.nhk.or.jp/netradio/files/swf/rtmpe.swf" \
--quiet --live --stop {2} -o $flvfile ) &'.format(rtmp, playpath, sduration))
233 lines.append('sleep 1m')
234 lines.append('radiru_noa.py {0} $m4afile'.format(channel))
235 lines.append('sleep {0}m'.format(duration))
236 lines.append('ffmpeg -loglevel error -i $flvfile -acodec copy $m4afile 237 lines.append('if [ -f "$m4afile" ]; then ')
238 lines.append(' rm -f $flvfile')
239 lines.append('fi')
240 lines.append('radiru_tag.py $m4afile')
241 lines.append('rm -f {}'.format(scriptname))
242 lines.append('')
243 script = "\n".join(lines)
このスクリプトでは、232行目でrtpdumpを使って受信したデータを"番組名.flv"という名前で保存してから、236行目でffmpeg を使ってそのファイルを"番組名.m4a"に変換しています。このあたりは録音した番組を携帯音楽プレイヤーで再生するための調整で、多くの携帯音楽プレイヤー(手元のはSony Walkman)はMPEG-4 Audioなファイル(.m4a)は再生できるものの、Adobe Flashなファイル(.flv)には対応していません。そのため、rtmpdumpでダウンロードしたAdobe Flashファイルをffmpegを使ってMP4ファイルに変換しているわけです。
Adobe Flashファイルの音声データはMPEG-4 Audioと同じHE-AAC(High-Efficiency Advanced Audio Codec)形式で記録されているので、ffmpegを使った変換の際も-acodec copyを指定して音声データのCODECはそのまま、データの格納形式のみAdobe Flash(.flv)からMP4(.m4a)に変換しています。
番組情報書き込み機能の修正
録音ファイルをMP3形式からMP4形式に変更するに伴い、番組情報をタグに書きこむ処理 にも修正が必要になりました。従来使っていたeyeD3というコマンドはMP3形式のタグ(ID3タグ)専用で、MP4形式のタグ(正確にはメタ・データ)は扱えません。そのため、新たにMP4形式のタグを操作するツールを調べてみたところ、灯台下暗し、Plamo Linuxにも収録しているmp4v2 というソフトウェアに含まれているmp4tags というコマンドが使えることに気づきました。
mp4tagsは文字通り、MP4形式のタグを操作するためのツールです。
$ mp4tags
mp4tags: You must specify at least one MP4 file.
usage mp4tags OPTION... FILE...
Adds or modifies iTunes-compatible tags on MP4 files.
-help Display this help text and exit
-version Display version information and exit
-A, -album STR Set the album title
-a, -artist STR Set the artist information
-b, -tempo NUM Set the tempo (beats per minute)
-c, -comment STR Set a general comment
...
-z, -artistid NUM Set the artist ID
-Z, -composerid NUM Set the composer ID
-r, -remove STR Remove tags by code (e.g. "-r cs"
removes the comment and song tags)
ざっと確認したところ、eyeD3とほぼ同じ情報が書き込めるようなので、以前はradiru_id3.pyとしていたタグファイル書き込み用のコマンドをradiru_tag.py に改名してMP4形式のタグを書き込むようにしました。mp4tagsは外部コマンドなのでsubprocessモジュール経由で利用しています。
48 def set_tag(file, tag):
49 import subprocess
50 mp4file = file.replace('.flv','.m4a')
51 filename = os.path.basename(mp4file)
52 date = filename.split("_")
53 mytitle = date[0] + '_' + tag['title'].encode('utf-8')
54 title = " -song '{}' ".format(mytitle)
55 album = " -album'{}' ".format(tag['album'].encode('utf-8'))
56 artist = " -artist '{}' ".format(tag['act'].encode('utf-8'))
57 if len(tag['contents']) > 0:
58 comment = " -comment '{}' ".format(tag['contents'].encode('utf-8'))
59 cmdlist = ['mp4tags ', file, title, album, artist, comment, mp4file]
60 else:
61 cmdlist = ['mp4tags ', file, title, album, artist, mp4file]
62
63 cmd = "".join(cmdlist)
64 p = subprocess.call(cmd, shell=True)
録音ファイルの確認
これらの修正を加えたradiru_rec.pyとradiru_tag.pyを使って、「 らじる☆らじる」の番組を録音してみました。
VLCでタグファイルの情報を確認すると、番組タイトルや出演者、楽曲情報等が正しく記録されているようです。
図1 VLCで録音したファイルのメディアデータを表示
これらの情報は、mp4v2パッケージに含まれているmp4info コマンドでも確認できます。
$ mp4info 2015-09-29-06-00_古楽の楽しみ-ヴィヴァルディの音楽-_002.m4a
mp4info version 2.0.0
2015-09-29-06-00_古楽の楽しみ-ヴィヴァルディの音楽-_002.m4a:
Track Type Info
1 audio MPEG-4 AAC LC, 3300.010 secs, 48 kbps, 48000 Hz
Name: 古楽の楽しみ -ヴィヴァルディの音楽-(2)
Encoded with: Lavf56.4.101
Comments: 今谷和徳
- ヴィヴァルディの音楽 -(2)「バイオリンと弦楽合奏および通奏低音のための協奏曲 二長調
作品8 第11 RV.210」ヴィヴァルディ作曲
(11分50秒)
(バイオリン)エンリコ・カサッツァ
(合奏)ラ・マニフィカ・コムニタ
...
しばらく新しいスクリプトを使ってみたところ、予約状況をチェックするradiru_check.py や予約を取り消すradiru_del.py にも修正が必要なことがわかり、それらも合わせて更新して、「 らじる☆らじる」録音用ツールのrtmpdump化が完了 しました。
Adobe Flashでは音声の圧縮にHE-AAC形式を利用しています。HE-AACはMP3よりも後発のCODECで、MP3よりも圧縮率が高く、低いビットレートでも高音質なことを売りにしています。実際、15分の語学番組を録音したファイルのサイズを比べてみたところ、1/3程度にまで小さくなっているようです。
$ ls -lh
-rw-r--r-- 1 kojima users 15M 8月 28日 07:01 2015-08-28-06-45_ラジオ英会話_2015_08_020.mp3
-rw-r--r-- 1 kojima users 5.3M 9月 4日 07:01 2015-09-04-06-45_ラジオ英会話_2015_09_005.m4a
また、WMAで録音していた際に悩まされていた配信の遅延もほぼ無くなる共に、rtmpdumpには何分記録するかを指定するオプション(--stop)も用意されているので、mplayerのようにFIFOを使って外から終了させるような処理も不要になって、録音スクリプトの信頼性も高まったように感じます。
これならもっと早くに乗り替えててもよかったな、と思う反面、「 壊れていないものを直すな」という考え方もあるので、判断は難しいところです(苦笑) 。
なお、今回紹介したradiru_rec.py等のスクリプトや処理に必要なrtmpdumpの新しいパッケージは筆者の日記のページ に添付しておきますので、ご興味のある方はダウンロードしてお試しください。
OSC 2015 Tokyo/Fallへの出展のお知らせ
最後に少し話題が変りますが、10/24-25に東京、日野市の明星大学で開催されるオープンソースカンファレンス2015 Tokyo/Fall にPlamo Linuxメンテナグループが出展することになりましたことを紹介します。
ブース展示には両日とも出展し、MacBookで動くPlamo Linuxの展示やlxc-plamoの紹介、インストールメディアの配布等を行う予定です。また初日(10/24)の11時からは、メンテナの松木さんがPlamo Linuxに関するセミナーを行います。
Plamo Linuxの主要メンテナも顔を揃えますし、配布するメディアには新バージョンとなるPlamo-6.0を収めようと鋭意作業を進めていますので、Plamo Linuxに興味ある方はぜひご来訪くださいませ。