19日に更新してた

アフィリエイトはないよ

golang の exec.Command で ffmpeg をやっと動かせた

golang をいじってみようかなと思ってはじめてみたら、とりあえず検索するとやりたいことが割と出てくるのでとても書きやすい。rust みたいに型と所有権で足踏みしてエラーメッセージで四苦八苦しなくていいし、できるようになった感がしてサンデープログラマーの自分にはいい感じ。

こんなに書きやすいなら python で書いた" ffmpeg を使ったダウンローダー"を移植してみようとやってみたところ、agouti を使えるようになったらサクサク進んだのですが最後の最後に exec.Command で ffmpeg をうまく通せない。

数日色々と弄り回してみたら、やっと原因がわかったのでご報告。

ffmpeg でストリーミングをダウンロードしようとしたら、ヘッダとか m3u ファイルはダブルクォーテーション*1をつけて

ffmpeg -headers "X-Radiko-AuthToken:aaaaaaaaa" -i "https://radiko.jp/~"

みたいな感じで書いていたのでそのまま入力して、

ffmpeg_command := "ffmpeg -headers \"X-Radiko-AuthToken:aaaaaaaaa\" -i \"https://radiko.jp/~\" ./a.m4a"
cmdArray := strings.Split(ffmpeg_command, " ")

cmd := exec.Command(cmdArray[0], cmdArray[1:]...)

みたいな感じから cmd.Run() してたのですが、これだとエラーが出るのでいかがしたものかと色々やってみたら、ダブルクォーテーションは入れないのが正解でした。クォーテーション*2もいらないみたい。

ついでに、例には挙げていないけれど半角スペースで分割すると、metadata の中に半角スペースを使った時に metadata の中で分割されてしまうのでカンマで区切って

ffmpeg_command := "ffmpeg,-headers,X-Radiko-AuthToken:aaaaaaaaa,-i,https://radiko.jp/,./a.m4a"
cmdArray := strings.Split(ffmpeg_command, ",")

cmd := exec.Command(cmdArray[0], cmdArray[1:]...)

とやってやったら、半角スペースを入れた metadata も通ったのでご査収ください。

ちなみに作ったものは async も go routine も使ってない*3ベタなものなのですが、ここ数回のダウンロードの所要時間を平均すると python のときと比べて所要時間が10秒ほど短くなっています。webpage の内容引っ張ってからの json の参照*4とかファイル周り以外、ほとんど ffmpeg のダウンロードだろうに差が出るものなんだなと感心しています。

*1:"

*2:'

*3:そもそも使い方がわかっていないので使えない

*4:json を struct に変換してくれるサイトには感動した。メッチャ楽。