気象通報を Linux で録音する【らじる★らじる】

気象通報、午後 16 時の放送のみに減らされてから、リアルタイムで聞ける機会が減って、リアルタイムで天気図を書くことが難しくなりましたね。ということで、気象通報を録音することにしました、って言う話。

# らじる★らじるを録音する

[らじる★らじる](https://www.nhk.or.jp/radio/)は、ラジオ放送をオンラインでストリーミング配信するサービスですが、HLS (HTTP Live Streaming) というプロトコルを用いています。詳しくは以下のサイトが参考になります。

[第95回　「らじる☆らじる」をHLS経由で：玩式草子─ソフトウェアとたわむれる日々｜gihyo.jp … 技術評論社](https://gihyo.jp/lifestyle/serial/01/ganshiki-soushi/0095)

## HLS に触れてみる

HLS は動画（らじる★らじるの場合は音声だけですが）を 10 秒程度の塊(MPEG2 TS (Transport Stream))に分けて、それを順に配信することで、ライブストリーミングを実現しています。そして、この形式でライブストリーミングを実現するためには、配信された TS ファイルをどの順で再生するかを指定することが重要になります。

再生順を指定するために、HLS では M3U という形式のプレイリストのフォーマットを用いています。M3U 自体は、HLS 特有のフォーマットではなく、他のメディアプレイヤーアプリでも用いられている形式です。すでに広まっている形式のプレイリストに則ることで、様々なメディアプレイヤーが HLS に対応しやすくなるという算段ですね。

とりあえず、らじる★らじるの HLS 形式の配信元は、[この XML ファイル](https://www.nhk.or.jp/radio/config/config_web.xml)に書いてあるので、例えば、札幌の NHK 第 2 放送を取得してみましょう。

https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-01.m3u8

上のリンクをそのまま開くと、ライブストリーミングが開始されます（動作はブラウザによると思われますが、macOS の Safari ではストリーミングが開始されました）。この URL が本当に M3U 形式であるか確認するために、`wget` してみましょう。

```
% wget https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-01.m3u8
--2019-06-16 22:20:47--  https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-01.m3u8
nhkradioakr2-i.akamaihd.net (nhkradioakr2-i.akamaihd.net) をDNSに問いあわせています... 58.159.200.101, 58.159.200.117
nhkradioakr2-i.akamaihd.net (nhkradioakr2-i.akamaihd.net)|58.159.200.101|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 1002 [application/x-mpegURL]
`1-r2-01.m3u8' に保存中

1-r2-01.m3u8                  100%[===============================================>]    1002  --.-KB/s 時間 0s       

2019-06-16 22:20:47 (28.1 MB/s) - `1-r2-01.m3u8' へ保存完了 [1002/1002]
```

中身を確認します。

```
% less 1-r2-01.m3u8

#EXTM3U
#EXT-X-VERSION:2
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:4655832
#EXTINF:10,
1-r2-20171211T180234-01-2327/1832.ts
#EXTINF:10,
1-r2-20171211T180234-01-2327/1833.ts
#EXTINF:10,
1-r2-20171211T180234-01-2327/1834.ts
#EXTINF:10,
1-r2-20171211T180234-01-2327/1835.ts
#EXTINF:10,
1-r2-20171211T180234-01-2327/1836.ts
#EXTINF:10,
1-r2-20171211T180234-01-2327/1837.ts
（以下略）
```

ここに書かれている ts ファイルを `wget` してみましょう。（ここに書いてあるコマンドをそのまま実行しても、もとの M3U プレイリストは時間ごとに更新されるので、実行できないと思われます。落としてきたプレイリストの中身を見て、wget する先を書き直してください）

```
% wget https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-20171211T180234-01-2327/1832.ts
--2019-06-16 22:23:59--  https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-20171211T180234-01-2327/1832.ts
nhkradioakr2-i.akamaihd.net (nhkradioakr2-i.akamaihd.net) をDNSに問いあわせています... 58.159.200.117, 58.159.200.101
nhkradioakr2-i.akamaihd.net (nhkradioakr2-i.akamaihd.net)|58.159.200.117|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 87044 (85K) [video/MP2T]
`1832.ts' に保存中

1832.ts                       100%[===============================================>]  85.00K  --.-KB/s 時間 0.03s    

2019-06-16 22:23:59 (2.98 MB/s) - `1832.ts' へ保存完了 [87044/87044]
```

ダウンロードされた TS ファイルを開いてみると、音声ファイルであることがわかります。macOS ならば、`open 1832.ts` とすれば、端末上からアプリケーションを起動できるので便利です。

ということで、配信元の実体は、テキストベースの M3U プレイリストであることがわかりました。

## ffmpeg に録音させる

ということで、某のアプリケーションに、HLS をダウンロードさせると、らじる★らじるを録音できる、という結論になります。

そして、ffmpeg の入力先（`-i` オプション）に HLS の URL を指定すると、ダウンロードできます。試しに、30 秒ほどデータをダウンロードさせましょう。`-t` オプションが、ダウンロードする時間の指定になります。

```
% ffmpeg -i https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-01.m3u8 -t 30 -movflags faststart -c copy -bsf:a aac_adtstoasc test.m4a
```

`test.m4a` を開くと、ダウンロードできていることが確認できます。

ということで、気象通報を録音するためには、毎日 16 時にこのコマンドを実行すればよいということがわかりました。今後のことを考えて、これをシェルスクリプト化します。とりあえず、`~/radio/` 以下に音声を保存することにして、スクリプトもそこに置くことにします。以下のシェルスクリプトでは、次のように変更しています。

- 配信に遅延が発生することも考慮して、録音時間を 22 分間としている。
- ファイル名を日付にしている。`$(date -I)` で、`date -I` の結果がそこに入ります。

```rec.sh
#! /bin/bash
ffmpeg -i https://nhkradioakr2-i.akamaihd.net/hls/live/511929/1-r2/1-r2-01.m3u8 -t 1320 -movflags faststart -c copy -bsf:a aac_adtstoasc ~/radio/$(date -I).m4a
```

実行権を与えるのを忘れてはいけません。

```
% chmod 744 rec.sh
```

# 指定時刻にコマンドを実行する。

指定時間にコマンドを実行するためには、`cron` を使いましょう。`cron` は、設定ファイルで指定さた時刻に、指定されたコマンドを実行してくれます。

まず、自分が `cron` で実行するようにしていたコマンドがあるかを確認してみましょう。

```
% crontab -l
crontab: no crontab for hitomisan
```

設定ファイルを書き換えるためには、`-e` オプションを使います。

```
% crontab -e
crontab: no crontab for hitomisan - using an empty one
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">なにが easiest じゃ。 <a href="https://t.co/FGk2ui3Gnc">pic.twitter.com/FGk2ui3Gnc</a></p>&mdash; ひとみさん🤮 a.k.a. Carele Smith (@CareleSmith9) <a href="https://twitter.com/CareleSmith9/status/1139910349879013376?ref_src=twsrc%5Etfw">June 15, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

作成する crontab の内容は次のようになります。一番最後の行以外は、初回作成時に勝手に書き込まれています。

```:crontab
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command

59 15 * * * ~/radio/rec.sh
```

ここで、`59 15 * * * ~/radio/rec.sh` は、「59 分」「15 時」「毎日」「毎月」「すべての曜日」に「`~/radio/rec.sh`」を実行するという設定になります。1 分早く録音を開始されるのは、ほかのコマンドとバッティングしないようにするためです。一般的に、0 分に cron するのは避けるべきと言われています。

# あとは録音されるのを待つだけ

ここまで設定を済ませると、あとは勝手に録音が行われます、やったね。

しかし、録音させるためには、録音開始の時点で、設定したパソコンが起動していて、設定したユーザーがログインしている必要があります。