rokkonet

PC・Androidソフトウェア・アプリの開発・使い方に関するメモ

副音声付き/音声多重TV録画tsファイルのmp4へのトランスコード

2024 May 26.
2023 Oct. 21.
2023 May 02.
2020 May 31.
2020 May 30.

出典

2020年版 デジタル放送録画の圧縮を最適化するFFmpegの使い方 - Simple Life in the digital age

[確認]NHK解説放送のmp4エンコード · Issue #244 · l3tnun/EPGStation · GitHub

https://haruo31.underthetree.jp/2014/11/25/%E5%89%AF%E9%9F%B3%E5%A3%B0%E3%81%AE%E3%81%82%E3%82%8Bm2ts%E3%82%92mp4%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AEffmpeg%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3/

https://centossrv.com/epgrec_una.shtml

EPGStationで使うFFmpeg 4.2.4のオプション設定を考える - Simple Life in the digital age

設定概要
  • ffmpegでの音声処理は、"-dual_mono_mode"オプション、"-filter_complex channelsplit"オプション、"-map 0:a:[ストリーム番号] "オプション、"-metadata:s:a:[ストリーム番号]"オプションの取捨選択・組み合わせとなり、試行錯誤を要する。
  • 録画番組の直前の番組のデータが録画冒頭に入り、意図しないトランスコード結果となることもある。
  • tsファイルの先頭4秒間を削除し、ファイルの先頭を録画直前の番組からの切替部以降とすることでトランスコードが安定する。

  "-ss 4"オプションをオプション記述の先頭に置く。

  • crfオプションを22〜25にする。(小さいほど高画質)。

  解像度1440×1080の場合、22〜23。
  解像度1920×1080の場合、24〜25。

  • -presetオプションはveryfastにする。

  • 音声・2ヵ国語放送は、音声格納方式が複数ある。

  ・1つの音声ストリームの中にステレオ方式で左チャンネルにメイン音声、右チャンネルにサブ音声が入っている方式。

  ・各音声が別々の音声ストリームに入っている方式。

  • 複数の音声が別々の音声ストリームに入っている時にffmpegで音声ストリームを指定するオプション

  -map 0:a:0 最初の入力ファイル(0)の音声(a)の最初のストリーム(0)を指定するオプション

  -map 0:a:1 最初の入力ファイル(0)の音声(a)の2番目のストリーム(1)を指定するオプション

  • ビデオストリームでは "-map 0:v:N"となる。

  • "-metadata:s:a:N"オプションで音声ストリームのタイトル・言語名を指定する。

  sはストリーム、aは音声を表しており、Nには0を基数にしたストリームの番号を記述する。
  -metadata:s:a:N title="XXX"でストリームのタイトルを指定する。
  -metadata:s:a:N language="YYY"でストリームの言語を指定する。
  languageにはISO 639-2 codeの言語名を指定する。

  • 1つのストリームの中で、Lチャンネルから主音声、Rチャンネルから副音声が出力されるような多重音声放送に対してのみ、-dual_mono_modeオプションでの音声分離が可能。
  • Mirakurunではdual_mono_mode番組にはAUDIOCOMPONENTTYPE変数が2となる。

  AUDIOCOMPONENTTYPE変数が2の時はdual_mono_modeオプションを使用できる。

  AUDIOCOMPONENTTYPEの値
   0x01 - Mono
   0x02 - Dual mono
   0x03 - Stereo
   0x04 - Multilingual stereo
   0x05 - Surround 5.1
   0x06 - AAC
   0x07 - HE-AAC

  • -dual_mono_modeオプションを使用する時は、どのモードで音声をデコードするかを指定する。

  FFmpegでは、以下のモードがサポートされている。
   -dual_mono_mode main
    主チャンネル(通常左チャンネル)の音声のみを使用する。
   -dual_mono_mode sub
    サブチャンネル(通常右チャンネル)の音声のみを使用する。
   -dual_mono_mode both
    主チャンネルとサブチャンネルの音声をミックスする。
   -dual_mono_mode both_separate
    両方のチャンネルを独立したモノラルトラックとして扱う。

  • -dual_mono_modeオプションは -iオプションよりも前におくこと。
  • 複数の音声が別々のストリームに入っている場合、-dual_mono_modeオプションは無効。指定しても最初のストリームだけが取り出される。

   複数の音声が別々のストリームに入っているケースで音声を分離したい場合は"-map 0:a:[ストリーム番号] "を用いるか、-filter_complex channelsplitオプション を用いる。

  • 最初の音声ストリームが日本語、2番目の音声ストリームが英語の番組のオプション
-map 0:v:0 -map 0:a:0 -map 0:a:1 -metadata:s:a:0 title="Japanese" -metadata:s:a:0 language="jpn" -metadata:s:a:1 title="Foreign" -metadata:s:a:1 language="eng"
  • 最初の音声ストリームが日本語メイン、2番目の音声ストリームが日本語サブの番組のオプション
-map 0:v:0 -map 0:a:0 -map 0:a:1 -metadata:s:a:0 title="main" -metadata:s:a:0 language="jpn" -metadata:s:a:1 title="sub" -metadata:s:a:1 language="jpn"
  • "-dual_mono_mode"オプションは録画番組の直前の番組の音声ストリーム情報に追従してしまって失敗することがある。

  • その他に付けておくオプション

  -analyzeduration 10M
  -probesize 32M
  -movflags faststart ストリーミング再生対応
   -ignore_unknown
  -max_muxing_queue_size 1024
  -crf 23
  -map 0:v:0
  -vf yadif,scale=-2:720 ディインターレース設定 & 縦解像度720での画面アスペクト調整
  -aspect 16:9
  -c:v libx264
  -f mp4
  -c:a aac -strict -2 実験的機能に対応
  -ar 48000
  -ab 192k
   縦解像度が720以下なら128k、縦解像度が720超なら192k?
  -ac 2 2チャンネルステレオ
  -dn  データストリームを除去
  -threads N N : CPUコア数
  -sn 字幕は無しとした方が安全

ffmpegコマンド例
  • 第1音声ストリームに日本語メイン音声、第2音声ストリームに外国語サブ音声が入っているtsファイルのトランスコード例


tsファイルのストリーム状況

$ ffprobe -i 2402262240BSBS15_0-101-NHK BS-BS世界のドキュメンタリー選▽ロシアに屈しないウクライナ市民ボランティア戦い\[二\]\[字\].m2ts

Input #0, mpegts, from '2402262240BSBS15_0-101-NHK BS-BS世界のドキュメンタリー選▽ロシアに屈しないウクライナ市民ボランティア戦い[二][字].m2ts':
  Duration: 00:50:06.75, start: 55892.604589, bitrate: 19107 kb/s
  Program 101 
    Metadata:
      service_name    : ?~<CE><C8><CB>!!<C2><D3>
      service_provider: ?~<CE><C8><CB>
  Stream #0:0[0x100]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv, bt709, top first), 1440x1080 [SAR 4:3 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn
    Side data:
      cpb: bitrate max/min/avg: 24000000/0/0 buffer size: 9781248 vbv_delay: N/A
  Stream #0:1[0x110]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, mono, fltp, 72 kb/s
  Stream #0:2[0x130]: Subtitle: arib_caption (Profile A) ([6][0][0][0] / 0x0006)
  Stream #0:3[0x138]: Data: bin_data ([6][0][0][0] / 0x0006)
  Stream #0:4[0x140]: Unknown: none ([13][0][0][0] / 0x000D)
  Stream #0:5[0x160]: Unknown: none ([13][0][0][0] / 0x000D)
  Stream #0:6[0x161]: Unknown: none ([13][0][0][0] / 0x000D)
  Stream #0:7[0x162]: Unknown: none ([13][0][0][0] / 0x000D)
  Stream #0:8[0x170]: Unknown: none ([13][0][0][0] / 0x000D)
  Stream #0:9[0x171]: Unknown: none ([13][0][0][0] / 0x000D)
  Program 102 
    Metadata:
      service_name    : ?~<CE><C8><CB>!!<C2><D3>
      service_provider: ?~<CE><C8><CB>
  Program 700 
    Metadata:
      service_name    : ?~<CE><C8><CB>?|<C7>!<<BF>?~<B1>
      service_provider: ?~<CE><C8><CB>
  Program 701 
    Metadata:
      service_name    : ?~<CE><C8><CB>?|<C7>!<<BF>?~<B2>
      service_provider: ?~<CE><C8><CB>
  Program 707 
    Metadata:
      service_name    : ?~<B7><B0><B7>?|<C1><E3><F3><CD><EB>
      service_provider: ?~<CE><C8><CB>
  Program 929 
    Metadata:
      service_name    : ?~<C4><F0><E1>?|<C0><A6><F3><ED>!<<C9>
      service_provider: ?~<C4><F0><E1>
  No Program
  Stream #0:10[0x12]: Data: epg



"-map 0:a:"オプションによるトランスコードコマンド例

$ ffmpeg -ss 4 -y -i 2402262240BSBS15_0-101-NHK BS-BS世界のドキュメンタリー選▽ロシアに屈しないウクライナ市民ボランティア戦い[二][字].m2ts -analyzeduration 10M -probesize 32M -movflags faststart -ignore_unknown -crf 23 -max_muxing_queue_size 1024 -dn -vf yadif,scale=-2:720 -map 0:v:0 -map 0:a:0 -map 0:a:1 -c:v libx264 -preset veryfast -c:a aac -strict -2 -ar 48000 -ab 192k -ac 2 -metadata:s:a:0 title=Japanese -metadata:s:a:0 language=jpn -metadata:s:a:1 title=Foreign -metadata:s:a:1 language=eng 2402262240BSBS15_0-101-world_documentary-ukraine-0.mp4

トランスコード結果
映像と2つの音声ストリームが正常にトランスコードできた。

$ ffprobe -i 2402262240BSBS15_0-101-world_documentary-ukraine-0.mp4

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2402262240BSBS15_0-101-world_documentary-ukraine-0.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:50:02.73, start: 0.000000, bitrate: 1851 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 960x720 [SAR 4:3 DAR 16:9], 1455 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc60.31.102 libx264
  Stream #0:1[0x2](jpn): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 194 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]


"-filter_complex channelsplit"オプション、"-metadata:s:a:"オプションによるトランスコードコマンド例

$ ffmpeg -ss 4 -y -i 2402262240BSBS15_0-101-NHK BS-BS世界のドキュメンタリー選▽ロシアに屈しないウクライナ市民ボランティア戦い\[二\]\[字\].m2ts -analyzeduration 10M -probesize 32M -movflags faststart -ignore_unknown -crf 23 -max_muxing_queue_size 1024 -dn -vf yadif,scale=-2:720 -map 0:v:0 -aspect 16:9 -c:v libx264 -f mp4 -preset veryfast -filter_complex channelsplit -metadata:s:a:0 title="Japanese" -metadata:s:a:0  language="jpn" -metadata:s:a:1 title="Foreign" -metadata:s:a:1 language="eng" -c:a aac -strict -2 -ar 48000 -ab 192k -ac 2 2402262240BSBS15_0-101-world_documentary-ukraine-1.mp4


トランスコード結果
2つの音声ストリームができたものの、どちらのストリームも日本語となった。

$ ffprobe -i 2402262240BSBS15_0-101-world_documentary-ukraine-1.mp4

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2402262240BSBS15_0-101-world_documentary-ukraine-1.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:50:02.73, start: 0.000000, bitrate: 1848 kb/s
  Stream #0:0[0x1](jpn): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 191 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 191 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 960x720 [SAR 4:3 DAR 16:9], 1455 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc60.31.102 libx264



"-filter_complex channelsplit"オプション、"-map 0:a:"オプションによるトランスコード例

$ ffmpeg -ss 4 -y -i 2402262240BSBS15_0-101-NHK BS-BS世界のドキュメンタリー選▽ロシアに屈しないウクライナ市民ボランティア戦い[二][字].m2ts -analyzeduration 10M -probesize 32M -movflags faststart -ignore_unknown -crf 23 -max_muxing_queue_size 1024 -dn -vf yadif,scale=-2:720 -map 0:v:0 -aspect 16:9 -c:v libx264 -f mp4 -preset veryfast -filter_complex channelsplit -map 0:a:0 -map 0:a:1 -metadata:s:a:0 title=Japanese -metadata:s:a:0 language=jpn -metadata:s:a:1 title=Foreign -metadata:s:a:1 language=eng -c:a aac -strict -2 -ar 48000 -ab 192k -ac 2 2402262240BSBS15_0-101-world_documentary-ukraine-2.mp4


トランスコード結果
2つの音声ストリームができたものの、どちらのストリームも日本語となった。

$ ffprobe -i 2402262240BSBS15_0-101-world_documentary-ukraine-2.mp4

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2402262240BSBS15_0-101-world_documentary-ukraine-2.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:50:02.73, start: 0.000000, bitrate: 2240 kb/s
  Stream #0:0[0x1](jpn): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 191 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 191 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 960x720 [SAR 4:3 DAR 16:9], 1455 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc60.31.102 libx264
  Stream #0:3[0x4](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:4[0x5](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 194 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]



  • 日本語と英語が1つのストリームに入っているDual Mono Mode(NHK総合19時ニュース)のトランスコード例


tsファイルのストリーム状況

$ ffprobe -i nhk1900news.m2ts

Input #0, mpegts, from 'nhk1900news.m2ts':
  Duration: 00:30:00.58, start: 4522.168656, bitrate: 14741 kb/s
  Program 43008
    Metadata:
      service_name    : ?NHK?Am9g?1??@8M
      service_provider:
  Stream #0:0[0x100]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002),
yuv420p(tv, bt709, top first), 1440x1080 [SAR 4:3 DAR 16:9], 29.97 fps,
29.97 tbr, 90k tbn
    Side data:
      cpb: bitrate max/min/avg: 20000000/0/0 buffer size: 9781248 vbv_delay: N/A
  Stream #0:1[0x110]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 144 kb/s
  Stream #0:2[0x130]: Subtitle: arib_caption (Profile A) ([6][0][0][0] / 0x0006)
  Stream #0:3[0x138]: Data: bin_data ([6][0][0][0] / 0x0006)
  Stream #0:4[0x140]: Unknown: none
([13][0][0][0] / 0x000D)
  Stream #0:5[0x160]: Unknown: none
([13][0][0][0] / 0x000D)
  Stream #0:6[0x161]: Unknown: none
([13][0][0][0] / 0x000D)
  Stream #0:7[0x162]: Unknown: none
([13][0][0][0] / 0x000D)
  Stream #0:8[0x170]: Unknown: none
([13][0][0][0] / 0x000D)
  Stream #0:9[0x171]: Unknown: none
([13][0][0][0] / 0x000D)
  Stream #0:10[0x172]: Unknown: none ([13][0][0][0] / 0x000D)
  Stream #0:12[0x111]: Audio: aac ([15][0][0][0] / 0x000F), 0 channels
  Program 43009
    Metadata:
      service_name    : ?NHK?Am9g?2??@8M
      service_provider:
  Program 43392
    Metadata:
      service_name    : ?NHK?7HBS?G??@8M
      service_provider:
  No Program
  Stream #0:11[0x12]: Data: epg



"-filter_complex channelsplit"オプション、"-metadata:s:a:"オプションによるトランスコードコマンド例

$ ffmpeg -ss 4 -y -i nhk1900news.m2ts -analyzeduration 10M -probesize 32M -movflags faststart -ignore_unknown -crf 23 -max_muxing_queue_size 1024 -dn -vf yadif,scale=-2:720 -map 0:v:0 -aspect 16:9 -c:v libx264 -f mp4 -preset veryfast -filter_complex channelsplit -metadata:s:a:0 title=Japanese -metadata:s:a:0 language=jpn -metadata:s:a:1 title=English -metadata:s:a:1 language=eng -c:a aac -strict -2 -ar 48000 -ab 192k -ac 2 nhk19news.mp4



トランスコード結果
日本語のストリームと英語のストリームが作成され、それぞれを独立して再生できた。

$ ffprobe -i nhk19news.mp4

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'nhk19news.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:29:56.56, start: 0.000000, bitrate: 1624 kb/s
  Stream #0:0[0x1](jpn): Audio: aac
(LC) (mp4a / 0x6134706D), 48000 Hz,
stereo, fltp, 192 kb/s (default)
    Metadata:
      handler_name    : SoundHandler      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](eng): Audio: aac
(LC) (mp4a / 0x6134706D), 48000 Hz,
stereo, fltp, 194 kb/s
    Metadata:
      handler_name    : SoundHandler      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 960x720 [SAR 4:3 DAR 16:9], 1228 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
    Metadata:
      handler_name    : VideoHandler      vendor_id       : [0][0][0][0]      encoder         : Lavc60.31.102 libx264



"-dual_mono_mode main"オプションによるトランスコード

$ ffmpeg -ss 4 -y -dual_mono_mode main -i nhk1900news.m2ts -analyzeduration 10M -probesize 32M -movflags faststart -ignore_unknown -crf 23 -max_muxing_queue_size 1024 -dn -vf yadif,scale=-2:720 -map 0:v:0 -aspect 16:9 -c:v libx264 -f mp4 -preset veryfast -c:a aac -strict -2 -ar 48000 -ab 192k -ac 2 nhk1900news-dual_mono_mode_main.mp4



トランスコード結果
音声が無くなり、映像のみになった。

$ ffprobe -i nhk1900news-dual_mono_mode_main.mp4

  Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'nhk1900news-dual_mono_mode_main.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:29:52.56, start: 0.000000, bitrate: 1150 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 960x720 [SAR 4:3 DAR 16:9], 1148 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
    Metadata:
      handler_name    : VideoHandler      vendor_id       : [0][0][0][0]      encoder         : Lavc60.31.102 libx264