直播技术调研

参考

[1] ffmpeg Capture
https://trac.ffmpeg.org/wiki/Capture/Desktop
[2] Capture Windows screen with ffmpeg
http://stackoverflow.com/questions/6766333/capture-windows-screen-with-ffmpeg
[3] gdigrab
https://ffmpeg.org/ffmpeg-devices.html#gdigrab
[4] ffmpeg User Datagram Protocol
https://ffmpeg.org/ffmpeg-protocols.html#udp
[5] ffmpeg Streaming Guide
https://trac.ffmpeg.org/wiki/StreamingGuide
[6] MPEGTS
https://en.wikipedia.org/wiki/MPEG_transport_stream
[7] Why rtp streaming of a .avi video file fails to be received?
http://stackoverflow.com/questions/15712983/why-rtp-streaming-of-a-avi-video-file-fails-to-be-received/16469378#16469378
[8] FFMPEG “Past duration 0.xxxxxx too large”
http://superuser.com/questions/902661/ffmpeg-past-duration-0-xxxxxx-too-large
[9] 3 seconds latency while streaming with Wowza Server
http://stackoverflow.com/questions/30300494/3-seconds-latency-while-streaming-with-wowza-server
[10] 从ffmpeg源代码分析如何解决ffmpeg编码的延迟问题
http://blog.csdn.net/nogodoss/article/details/19112807
[11] screen-capture-recorder
https://github.com/rdp/screen-capture-recorder-to-video-windows-free
[12] virtual-audio-capture-grabber-device
https://github.com/rdp/virtual-audio-capture-grabber-device
[13] Low-latency streaming using ffmpeg
http://superuser.com/questions/382052/low-latency-streaming-using-ffmpeg
[14] Setup for a live (low-latency) audio video broadcast over Wi-Fi?
http://superuser.com/questions/762470/setup-for-a-live-low-latency-audio-video-broadcast-over-wi-fi
[15] How to stream video and audio from a Raspberry Pi with no latency
http://blog.tkjelectronics.dk/2013/06/how-to-stream-video-and-audio-from-a-raspberry-pi-with-no-latency/
[16] raspi-camera-gstreamer-10-w-windows
http://robogoby.blogspot.fr/2014/01/raspi-camera-gstreamer-10-w-windows-7.html
[17] H.264 “zero” latency video encoding and decoding for time-critical applications
http://www.eetimes.com/document.asp?doc_id=1273759

屏幕捕捉(屏幕录制)

  • 使用内置 GDI screengrabber [2,3,1]
    ffmpeg -f gdigrab -framerate 10 -i desktop [output]

  • 使用 dshow [1]

视频广播/多播

MPEG TS + UDP

使用 -f mpegts 输出格式以及 udp 输出协议,并使用多播地址:

ffmpeg -f gdigrab -framerate 24 -i desktop -f mpegts -c:v libx264 udp://236.0.0.2:2000

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -b:v 800K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 udp://236.0.0.2:2000?pkt_size=1000&buffer_size=8000

Linux:

ffmpeg -video_size 1366x768 -framerate 10 -f x11grab -i :0.0 -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -b:v 800K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 “udp://236.0.0.2:2000?pkt_size=1000&buffer_size=8000”

如果不指定 -video_size 1366x768 则尺寸变成了 640x480?

注意,如果不指定视频编码(-c:v libx264),则 mpegts 默认使用 mpeg2 视频编码,比起h264,CPU占用率较低,但数据量大得多。

接收端,以 ffplay 为例: ffplay udp://236.0.0.2:2000

更多的参数见[4]。
MPEGTS 详见[6]。
有时候某个多播IP地址不可用(ffmpeg 并不报错,但抓包时看不到任何包发出),可以换个IP地址试试,如 236.0.0.2。原因不明。

-filter:v fps=10 用来避免帧率不稳定的问题(“Past duration too large”)[8]。

在使用某些无线路由器(如思科linksys E3000)的时候,ffmpeg 组播时会出现内存泄漏,内存占用会迅速上升直至崩溃。
使用有线网络时也出现了类似的现象。
错误信息:[output stream 0:0 @ 051592e0] 100 buffers queued in output stream 0:0, something may be wrong.

MPEG TS + UDP,由 ffmpeg 产生,vlc 转发

ffmpeg:
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -b:v 800K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 udp://127.0.0.1:2000?pkt_size=1000&buffer_size=8000

vlc:
“C:\Program Files (x86)\VideoLAN\VLC\vlc.exe” -vvv -I dummy udp://@127.0.0.1:2000 :sout=#udp{dst=236.0.0.2:2000} :sout-keep

RTSP + UDP,使用 revmischa rtsp-server

运行 rtsp-server.pl;

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f rtsp -rtsp_transport udp -muxdelay 0.5 -c:v libx264 -b:v 700K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 “rtsp://127.0.0.1:5545/d”

注意:-rtsp_transport udp_multicast 目前尚不支持,只能用 udp 或 tcp。

播放 rtsp:///d

存在的问题:
(1)用 -rtsp_transport tcp 的时候,revmischa rtsp-server 似乎有问题,vlc 无法播放。
(2)用 -rtsp_transport udp 的时候,wifi 条件下 vlc 花屏很严重,似乎比 MPEG TS + UDP 还糟糕。

RTSP,使用 live555

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -b:v 800K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300:bframes=10 udp://239.255.42.42:1234?pkt_size=1300&buffer_size=8000

testOnDemandRTSPServer.exe

访问:rtsp://192.168.40.85:8554/mpeg2TransportStreamFromUDPSourceTest

ffplay 并不成功:
[rtsp @ 054f9ee0] UDP timeout, retrying with TCPB sq= 0B f=0/0
nan : 0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0

vlc 也没有反应。

openRTSP 也无法播放:
Receiving streamed data…
Missing sync byte!

testOnDemandRTSPServer.exe 的输出是
MultiFramedRTPSource::doGetNextFrame1(): The total received frame size exceeds the client’s buffer size (48). 472 bytes of trailing data will be dropped!

减小 pkt_size=1300 也没什么效果,减小到 600 以下时 openRTSP 更早地失败。

改用 ffmpeg rtp multicast 则 testOnDemandRTSPServer 似乎收不到数据:
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f rtp -c:v libx264 -b:v 700K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300 rtp://239.255.42.42:1234

RTSP,使用 vlc 作为流服务器

单播到localhost
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -b:v 800K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000

VLC:
“C:\Program Files (x86)\VideoLAN\VLC\vlc.exe” -vvv -I dummy –dummy-quiet udp://@127.0.0.1:2000 :sout=#rtp{sdp=rtsp://:554/} :sout-keep

访问 url: rtsp://192.168.40.85

效果:用 ffplay/vlc + wifi 播放时花屏严重。

http,使用 vlc 作为流服务器

单播到localhost
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -b:v 400K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000

缩小画面
ffmpeg -f gdigrab -framerate 20 -i desktop -filter:v fps=20 -filter:v scale=640:-1 -f mpegts -muxdelay 0.5 -c:v libx264 -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000

注意 -filter:v scale 要在 -filter:v fps 之后,否则没有效果(bug?)。

VLC:
“C:\Program Files (x86)\VideoLAN\VLC\vlc.exe” -vvv -I dummy –dummy-quiet “udp://@127.0.0.1:2000” “:sout=#duplicate{dst=http{mux=ffmpeg{mux=mpegts},dst=:8080/}}”

注意,如果用 vlc 的GUI,则 http 模式下默认的 mux 是 flv 而不是 mpegts。flv 的问题是在很多播放器上的延迟很大,mpegts 则好很多,与udp + mpegts差不多,PC 上 ffplay、vlc在可以做到2秒,但android上vlc、vitamio则在5-8秒。

不过,http 模式的延迟仍然有些问题:在wifi上随着播放的进行,有些播放器的延迟会逐渐增大(如ffplay、vitamio)。

RTP + UDP multicast

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f rtp -c:v libx264 -b:v 700K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300 rtp://236.0.0.2:2000 > d.sdp

ffmpeg -f gdigrab -framerate 20 -i desktop -filter:v fps=20 -f rtp -c:v libx264 -b:v 1000K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300:bframes=10 rtp://236.0.0.2:2000 > d.sdp

以上命令创建 d.sdp 文件,将其用任意方法传递到接收端,然后用
ffplay d.sdp 来播放。
此方法参考[7]。236.0.0.2 也可以换成单播地址。

也可以将 d.sdp 部署到 http 服务器上,用播放器访问 http://host:port/d.sdp 来播放。
ffplay 和 MX player 都支持,但 vlc 似乎不支持(不论是否给予.sdp以正确的content-type)。

slice-max-size 较小时能减小丢包的影响,但较老的 ffplay 播放一段时间后会停止播放,MX player 似乎没有这个问题。

http, ffmpeg 做服务器

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -listen 1 -f mpegts -muxdelay 0.1 -c:v libx264 -b:v 400K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300 http://127.0.0.1:8080

局限性:延迟较大(本地到本地也要2秒);只能服务一个客户端(支持多客户端的 -listen 2 还没有实现)。

rtmp

ffmpeg + nginx + nginx-rtmp-win32

nginx.conf:

rtmp {
server {
listen 1935;

    application live {
        live on;
    }

    application hls {
      live on;
      hls on;  
      hls_path temp/hls;  
      hls_fragment 8s;  
    }
}

}

http {
server {
listen 8087;

    location / {
        root www;
    }

    location /stat {
        rtmp_stat all;
        rtmp_stat_stylesheet stat.xsl;
    }

    location /stat.xsl {
        root www;
    }

  location /hls {  
    #server hls fragments  
    types{  
      application/vnd.apple.mpegurl m3u8;  
      video/mp2t ts;  
    }
    root temp;
    #alias temp/hls;
    expires -1;
    add_header Cache-Control no-cache;
    add_header Access-Control-Allow-Origin *;
  }
}

}

推送 rtmp 流:

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f flv -c:v libx264 -b:v 400K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300 rtmp://localhost:1935/live

播放 rtmp:
ffplay rtmp://localhost:1935/live

推送 HLS 流:
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f flv -c:v libx264 -b:v 400K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300 rtmp://localhost:1935/hls

播放 HLS:
ffplay http://localhost:8087/hls/.m3u8

要注意 hls_fragment 不应小于关键帧间隔(-g / -framerate),否则 ffplay 无法播放。

点到点

ffmpeg -f gdigrab -framerate 24 -i desktop -f mpegts -c:v libx264 udp://172.16.9.83:2000

ffmpeg -f gdigrab -framerate 24 -i desktop -vf scale=320:-1 -f mpegts -c:v libx264 udp://172.16.9.83:2000

播放器

用 vlc 播放时,url 要写成 udp://@236.0.0.2:2000 的形式,否则是黑屏。
用 vlc 播放点到点 udp 的 url 可以形如 udp://@:1234

有的 android 设备上 vlc 播放 MPEGTS UDP 似乎有问题。
MX Player 可以播放,url 格式是 udp://ip:port ,如果是点到点,ip可以写 127.0.0.1 。

延迟

默认配置下延迟会多达3-5秒。编码器加入 -tune zerolatency 后可以显著减小。
播放器也可能引入缓冲延迟,vlc 的默认缓冲延迟是1s,可以更改到0.1s。ffplay -fflags nobuffer 也可以减小缓冲延迟。
这样总的延迟可以降低到1-2秒。

使用 intra-refresh 会增加延迟,尤其是在低帧率下,如帧率分别为5、10、30时,延迟大约是4、3、1秒左右。
不用intra-refresh则延迟对帧率的敏感性降低,但也有影响,如帧率分别为5和10时,延迟大约是2秒和1秒左右。

想要把帧率降低到1秒以下就比较困难了。

编码器上减小 -g 20,减小buffer_size,设置 -x264opts bframes 效果都不明显。这是现在用的配置:

ffmpeg -loglevel debug -f gdigrab -framerate 20 -i desktop -f mpegts -c:v libx264 -b:v 1000K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1300:bframes=10 udp://236.0.0.3:2000?pkt_size=1300&buffer_size=8000

bframes设置过小,如0-4可能严重降低压缩效果(同等码率下画面质量下降)。

这个配置下(用mpeg2编码器)延迟可以减小到1秒左右:
ffmpeg -f gdigrab -framerate 30 -i desktop -f mpegts -b:v 4000 udp://192.168.40.45:2000

不过,减小播放器的缓冲对播放的稳定性有负面影响,有可能出现花屏后无法恢复或播放停止的问题。VLC的缓冲时间在0.1秒似乎不够稳定。

[13] 提到用 ffmpeg 和 mplayer 可以将延迟降低到 0.8 秒。根据[14,15],用 gstreamer 可以实现 100 多 ms 的延迟。

Android 自带的 MediaPlayer 和 VideoView 类的播放延迟较大且不可调节,建议用Vitamio[9]。

带宽的影响

讨论延迟时,需要考虑网络带宽的影响。

  • 带宽绝对不足(小于平均码率)
    延迟必将随时间无限增加,这是无法使用的。

  • 带宽绝对充足(大于峰值码率)
    几乎不增加额外的缓冲延迟,网络部分的延迟只是网络本身的延迟。
    峰值码率其实并没有合适的定义,因为视频是以帧为单位离开编码器的,如果帧的传输时间趋于零,瞬时码率就会趋于无穷大。
    考虑到在下一帧到来前传输完毕当前帧就可以将延迟控制在一帧以内,所以我们定义瞬时码率为“帧大小/帧间隔”。
    压缩过的视频各帧的大小是不同的,关键帧(I)要显著大于预测帧(P、B),可以相差几十倍,因此码率峰值出现在关键帧处。
    例如,1366x768 的桌面截屏在平均码率 500Kbps,帧率 10fps ,关键帧间隔 4 秒时,关键帧大小可达 150~300KB ,因此码率峰值可达 12~24Mbps,
    是平均码率的 24~48 倍。由此可见带宽绝对充足是相当不易满足的,特别是有多个客户端的情况下。

  • 带宽相对充足(大于平均码率,小于峰值码率)
    这是比较常见的情况。如果播放端的帧率保持均匀,则关键帧的传输延迟会加在总延迟上。计算方法是:关键帧大小/网络带宽。例如关键帧大小 150~300KB,
    带宽 1Mbps,则传输延迟是 1.2~2.4 秒。因此可以推论,没有关键帧的编码方式(H.264 intra-refresh)有助于减小这项延迟。不过应注意,intra-refresh
    的码率也不是完全平均的,仍存在周期性的峰值,只不过峰值较小。

  • 带宽相对充足,但是随时间波动,波谷小于平均码率
    这也是比较常见的情况。波谷的存在可以造成额外的“缓冲延迟”和“卡顿延迟”:播放器为了在波谷处不卡顿,可以维持较大的输入缓冲区,缓冲的时长就直接加在延迟上,即缓冲延迟。
    如果播放器采用较小的初始输入缓冲区,遇到波谷时缓冲区耗尽,将被迫暂停播放,待缓冲区恢复后再开始,暂停播放的这段时间接下来就成了“卡顿延迟”;
    接下来来到带宽波峰时,缓冲区中的数据量又会迅速上涨(假定服务器端还没有丢弃波谷期间来不及传输的数据),“卡顿延迟”又转换为“缓冲延迟”。“卡顿延迟”是累积的,每卡顿一次都会增加总延迟,因此是需要着力解决的问题。
    解决卡顿延迟积累的必要手段是“自适应播放速度”:当缓冲的时长过长时,则加快播放速度,直到缓冲的时长减小到理想值,再变成正常速度。除了加快播放速度,也可以直接跳帧,这算是特殊情况。

不足和充足两种情况。这里所说的不足是相对不足,因为

初始延迟

刚开始播放的延迟至少由两部分构成:
(1)探测视频格式。ffplay 的参数 -analyzeduration 300 或 -probesize NNN 可以减小探测所需的时间。
(2)等待下一个关键帧。
不过,似乎仍有以上两者之外的延迟存在。ffplay 从探测格式结束到显示画面的时间似乎相当长,vitamio也是。

画面质量

参考命令:
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.1 -c:v libx264 -b:v 400K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000

视频分辨率:1399x768

ffmpeg 的命令行的输出中,q值是个很好的画面质量参考。q值大于32就有些难以忍受了,小于27则没有明显缺陷。

低动态画面(ffmpeg 的命令行窗口,每秒更新一次)
参数 q值
-b:v 600K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 25-28
-b:v 600K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 30-32
-b:v 600K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=2000:bframes=10 22-23
-b:v 600K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 23-25

-b:v 400K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=2000:bframes=10 29-32
-b:v 400K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 27-28
-b:v 400K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=2000:bframes=10 37-39
-b:v 400K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=5 36-38
-b:v 400K -g 60 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 23-25

从以上数据看出,对画面质量影响最大的是码率(-b:v)、关键帧间隔(-g)。slice-max-size 的影响有些奇怪。

采用 -crf 来测试

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.5 -c:v libx264 -crf 34 -b:v 800K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000

注意:实际得到的 q 值要比指定的 -crf 低 3-4。

参数 q 码率
-crf 34 -b:v 800K -g 60 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 29-31 416
-crf 34 -b:v 800K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 29-31 540
-crf 34 -b:v 800K -g 30 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 30-31 595
-crf 34 -b:v 800K -g 20 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=8000:bframes=10 29-31 825

-crf 34 -b:v 800K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=12000:bframes=10 29-31 560
-crf 34 -b:v 800K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=4000:bframes=10 29-31 564
-crf 34 -b:v 800K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=2000:bframes=10 29-31 566
-crf 34 -b:v 800K -g 40 -tune zerolatency -x264opts intra-refresh=1:slice-max-size=1000:bframes=10 29-31 603

不使用 intra-refresh 而使用 -crf 时,q 值事实上并不恒定,最大值接近于-crf的指定值,但平均值要低 7 左右。
slice-max-size 的影响并不明确。

降低帧率会大大降低高动态画面的码率,不过帧率从10降低到5会增加1秒左右的延迟。

不过,使用 intra-refresh 和 -g 60 时(无论是否用 -crf),Vitamio 有较大可能出现如下错误:

03-07 17:30:30.820: D/Vitamio[5.0.0]Player: [mpegts @ 0xe39ae400] decoding for stream 0 failed
03-07 17:30:30.820: D/Vitamio[5.0.0]Player: [mpegts @ 0xe39ae400] Could not find codec parameters for stream 0 (Video: h264 ([27][0][0][0] / 0x001B), none): unspecified size
03-07 17:30:30.820: D/Vitamio[5.0.0]Player: Consider increasing the value for the ‘analyzeduration’ and ‘probesize’ options
03-07 17:30:30.820: E/Vitamio[5.0.0]Player: av_find_stream_info: Operation not permitted : -1
03-07 17:30:30.820: D/Vitamio[5.0.0]Player: CLEAN START
03-07 17:30:30.820: E/Vitamio[5.0.0]Player: error (1, -1)

-g 40 则正常,-g 50 也有一定的可能出错,不使用 intra-refresh 也一切正常。

不使用 intra-refresh,使用帧率5-10。
ffmpeg -f gdigrab -framerate 5 -i desktop -filter:v fps=5 -f mpegts -muxdelay 0.1 -c:v libx264 -crf 34 -b:v 800K -g 20 -tune zerolatency “udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000”

ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.1 -c:v libx264 -crf 36 -b:v 800K -g 40 -tune zerolatency “udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000”

低动态
参数 q 码率 延迟vt ffplay
-framerate 5 -crf 34 -b:v 800K -g 20 23-27 477 3 2
-framerate 10 -crf 34 -b:v 800K -g 40 23-27 535 1-2 1
-framerate 10 -crf 36 -b:v 800K -g 40 27-32 496 1-2 1

高动态
参数 q 码率 延迟vt ffplay
-framerate 5 -crf 34 -b:v 800K -g 20 25-30 504 3 2
-framerate 10 -crf 34 -b:v 800K -g 40 25-30 630 1-2 1
-framerate 10 -crf 36 -b:v 800K -g 40 30-33 630 1-2 1

不用 intra-refresh,固定码率
ffmpeg -f gdigrab -framerate 10 -i desktop -filter:v fps=10 -f mpegts -muxdelay 0.1 -c:v libx264 -b:v 400K -g 40 -tune zerolatency “udp://127.0.0.1:2000?pkt_size=1000&buffer_size=2000”

低动态
参数 q 码率
-framerate 10 -b:v 400K -g 40 24-29 500
-framerate 10 -b:v 360K -g 40 25-33 419

高动态
参数 q 码率
-framerate 10 -b:v 400K -g 40 30-33 580
-framerate 10 -b:v 360K -g 40 32-40 460

NetBalancer 测试
在 -framerate 10 -b:v 400K -g 40 条件下,wifi->wifi,不加限制时,vlc http 平均码率403Kbps,最大码率1.3Mbps,vitamio延迟2秒。
如果施加 的限速,则延迟会逐渐增加,几分钟后达到数十秒。900Kbps

限速Kbps 延迟
600 逐渐增加
700 逐渐增加
800 3秒,高动态画面逐渐增加
900 3秒

注意,NetBalancer 上显示的vlc实际传输的码率要明显大于ffmpeg显示的码率(高出100-200Kbps),这可能是因为存在大量的TCP重传(wireshark上可见)。

mpegts + udp + crf 测试

ffmpeg -f gdigrab -framerate 20 -i desktop -filter:v fps=20 -f mpegts -muxdelay 0.1 -c:v libx264 -crf 34 -b:v 1000K -g 40 -tune zerolatency -x264opts “intra-refresh=1:slice-max-size=1000:bframes=10” “udp://236.0.0.2:2000?pkt_size=1000&buffer_size=8000”

参数 q 码率 延迟vt
-framerate 20 -crf 34 -g 40 31-32 614Kbps 1(最佳,网络不良时会增加)
-framerate 30 -crf 34 -g 60 31-32 800Kbps 1(最佳,网络不良时会增加)

同时捕获音频

用以下命令列出 directshow 设备:
ffmpeg -list_devices true -f dshow -i dummy

会输出形如
[dshow @ 050f3ac0] DirectShow audio devices
[dshow @ 050f3ac0] “楹﹀厠椋?(Realtek High Definition Audio)”
[dshow @ 050f3ac0] Alternative name “@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{3BB77F21-6D9B-4488-9345-43451347FB2C}”

设备名中可能有乱码,这时可以采用 “Alternative name”:

ffmpeg -f gdigrab -framerate 20 -i desktop -f dshow -i audio=”@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{652BEE08-CE02-47B0-B9F9-A129535509B5}” -filter:v fps=20 -f mp4 -c:v libx264 -crf 30 -b:v 1000K -g 60 -pix_fmt yuv420p -c:a aac -b:a 64K d.mp4

ffmpeg -f gdigrab -framerate 20 -i desktop -f dshow -i audio=”麦克风 (Realtek High Definition Audio)” -filter:v fps=20 -f mp4 -c:v libx264 -crf 30 -b:v 1000K -g 60 -pix_fmt yuv420p -c:a aac -b:a 64K d.mp4

ffmpeg 似乎无法直接捕获扬声器的输出,不过可以用 virtual-audio-capture-grabber-device [12] 来实现。安装 [11]后,用
audio=”virtual-audio-capturer” 可以捕获扬声器的输出。这是个 DirectShow filter,文件名是 audio_sniffer.dll 和 audio_sniffer-x64.dll,用 regsvr32 可以注册。

ffmpeg -f gdigrab -framerate 20 -i desktop -f dshow -i audio=”virtual-audio-capturer” -filter:v fps=20 -f mp4 -c:v libx264 -crf 30 -b:v 1000K -g 60 -pix_fmt yuv420p -c:a aac -b:a 64K d.mp4

高级缩放

可以在scale中使用

运算符:
* /

函数:
min(a,b)
max(a,b)
trunc(a) 下取整
gt(a,b):boolean 大于
if(a:boolean,b,c) 如果a,则返回b,否则返回c

常量:
iw 输入画面宽度,像素
ih 输入画面高度,像素
a 宽高比
w=-n 或 h=-n :n是正整数。宽或高按保持高宽比的原则计算出来,并且是 n 的整数倍。

其他选项
force_original_aspect_ratio=decrease|increase|disable

举例:
-filter:v scale=w=min(iw,1000):h=min(ih,700):force_original_aspect_ratio=decrease

注意,yuv420p 等格式要求图像的宽高都是偶数,有的视频编码器要求图像的宽或高是4、8、16的倍数,这时候可以用 w=-n 或 trunc(w/n)*n。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值