12783


ffmpegでWebカメラのライブストリーミングを実装しています。  
ライブなのでできる限り遅延を短くしたいものです。  
以下のコマンドでsegment_timeとsegment_list_sizeオプションの値を小さくして制御しようと考えています。

[code]

    /usr/local/bin/ffmpeg \
       -f v4l2 -thread_queue_size 1024 -s 640x480 -i /dev/video0 -r 15  \
       -f alsa -thread_queue_size 1024 -i sysdefault:CARD=U0x46d0x994 -ac 2 \
       -c:v libx264 -preset fast -pix_fmt yuv420p -s 640x480 -b:v 1024k -vsync passthrough \
       -c:a aac -b:a 128k -strict -2 \
       -f ssegment -segment_format mpegts -segment_list test.m3u8 \
       -segment_list_type hls -segment_time 10 -reset_timestamps 1 \
       -segment_list_size 3 -segment_list_flags +live \
       -threads 4 out%03d.ts
    
[/code]

出力された.m3u8ファイルは下記のようになっています、segment_timeオプションが効かない様子です。

[code]

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-MEDIA-SEQUENCE:32
    #EXT-X-ALLOW-CACHE:YES
    #EXT-X-TARGETDURATION:17
    #EXTINF:16.666667,
    out032.ts
    #EXTINF:16.733333,
    out033.ts
    #EXTINF:16.666667,
    out034.ts
    
[/code]

パラメータに何が足りないのでしょうか？  
目的はライブの遅延を短くしたいです、他にいい方法があれば教えてくだい。  
よろしくお願いします。


CC BY-SA 3.0
2015-07-27T03:14:00.190
12736
2015-07-29T07:54:53.777
9655
question
ffmpeg
ffmpegのsegment_timeオプションが効かないのか


[segment muxer](http://www.ffmpeg.org/ffmpeg-formats.html#Options-7)の
`-break_non_keyframes 1` オプションで問題を回避しました。

[code]

    /usr/local/bin/ffmpeg -f v4l2 -thread_queue_size 1024 -s 640x480 -i /dev/video0 -r 30 \
                          -f alsa -thread_queue_size 1024 -i sysdefault:CARD=U0x46d0x994 -ac 2 \
                          -c:v libx264 -preset fast -pix_fmt yuv420p -s 640x480 \
                          -b:v 1024k -quality good -c:a aac -b:a 128k -strict -2 \
                          -f ssegment -segment_format mpegts -segment_list test.m3u8 -break_non_keyframes 1 \
                          -segment_list_type hls -segment_time 10 -segment_list_size 3 -segment_list_flags +live -threads 4 out%03d.ts
    
[/code]


CC BY-SA 3.0
2015-07-27T12:58:15.210
12749
2015-07-27T12:58:15.210
9655
12736
answer


x264エンコードパラメータのGOP長（キーフレーム周期）が原因です。FFmpeg/libx264では[オプション`-g`](https://sites.google.com/site/linuxencoding/x264-ffmpeg-
mapping)で指定可能です。

HLSを構成するメディアセグメントファイルでは、各セグメント先頭をキーフレーム(Key-
frame)とする必要があります。今回のケースではFFmpegの自動補正により、実質セグメント長を17秒(`#EXT-X-
TARGETDURATION:17`)として処理したようです。  
`-g`デフォルト値は250フレームであり、映像フレームレートに15fps(`-r
15`)を指定していますから、計算される最小セグメント長は250÷15＝16.666667秒、これはm3u8ファイル中の`#EXTINF`タグ出力とも合致します。

HLSセグメント分割長を10秒(`-segment_time 10`)としたい場合は、GOP長もあわせて`-g
150`（15fpsで10秒長）指定が必要です。注意点として、オプション`-g`はlibx264に対するパラメータのため、`-c:v
libx264`より後ろ（かつ`-c:a aac`より前）に記述する必要があります。

* * *

> 目的はライブの遅延を短くしたいです、他にいい方法があれば教えてくだい。

HLSの運用では、セグメント長[10秒が推奨値](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html)とされており、それ以外でも[2～15秒程度が一般的](https://www.dash-
player.com/blog/2015/04/using-the-optimal-segment-length-for-adaptive-
streaming-formats-like-mpeg-dash-hls/)だと思います。

GOP長／セグメント長を短くするほど、ライブの遅延量を小さくできます。一方でGOP長を短くしすぎると、映像エンコード画質が劣化したり、時系列的な画質が不安定になることもありますから、そのあたりのトレードオフを考慮する必要があります。


CC BY-SA 3.0
2015-07-29T03:21:57.630
12783
2015-07-29T07:54:53.777
2015-07-29T07:54:53.777
49
49
12736
answer