环境:
推流端: ffmpeg
server端: media-soup
接收端: chrome
设置:
export SERVER_URL=https://x.x.x.x:4443 //注意端口号是4443
export SERVER_URL=https://118.178.125.107:4443
export ROOM_ID=1; // 需要先在浏览器里边加入房间号1; 否则推流会失败;
export MEDIA_FILE=./test.webM // 待推流的webM文件 (webM用于封装opus和vp8)
1. chrome 默认不支持h264视频流播放(当然可以通过设置支持)
https://www.infoq.cn/article/2011/01/chrome-h264
ffmpeg 推流到media-soup, 接收端是google浏览器;
当推h264流时, 提示"http: warning: HTTP 500 unsupported codec [mimeType:video/h264, payloadType:101]", 不支持编码, h264这么通用的编码格式居然不支持, 于是怀疑media-soup配置可能有问题, 后来google搜索了一下, 发现原来是chrome放弃了对h264的支持, 转到自家的vp8/vp9系列;
另外, 自带的ffmpeg居然不支持libfaac, 感觉世界开始抛弃非开源项目了;
2. 推流格式: audio: opus video: vp8
不管什么格式的音视频, ffmpeg都能给它转码到 vp8/opus, 所以, 只要rtp参数填写为正确的opus和vp8 即可, 在chrome里边也能正常显示;
其它: google支持的格式 opus对标aac, vp8对标h264, vp9对标h265;
ffmpeg.sh 是边转码, 边推流, 转码耗时本来就大, 可能会影响推流; 所以我们先转码为chrome能播的音视频流
需要转码为音频: opus, 视频: vp8, 由于mp4暂不支持vp8, 所以需要用webM封装格式;
ffmpeg转码参考:
视频缩放和裁剪参考:
由于需要适配浏览器播放窗口大小和最大码率大小, 故将原有的1080p视频缩放为200p, 然后再裁剪到适合浏览器窗口播放的大小; 视频码率降低到300kbps, 码率太大容易卡顿. 因为推流端没有做码率自适应;
ffmpeg -i mj-test.mp4 -c:a libopus -ac 2 -ar 48000 -pix_fmt yuv420p -vf scale=355:200,crop=200:170:0:0 -c:v libvpx -b:v 300k -deadline realtime o.webM
ffmpeg推流脚本为:
ffmpeg \
-re \
-v info \
-stream_loop -1 \
-i ${MEDIA_FILE} \
-map 0:a:0 \
-acodec copy \
-map 0:v:0 \
-c:v copy\
-f tee \
"[select=a:f=rtp:ssrc=${AUDIO_SSRC}:payload_type=${AUDIO_PT}]rtp://${audioTransportIp}:${audioTransportPort}?rtcpport=${audioTransportRtcpPort}|[select=v:f=rtp:ssrc=${VIDEO_SSRC}:payload_type=${VIDEO_PT}]rtp://${videoTransportIp}:${videoTransportPort}?rtcpport=${videoTransportRtcpPort}"
此处的audio和video都不再转码.
最终效果为:
ffmpeg 推流与mediasoup server交互流程:
1. 校验roomid是否存在(也可以自己创建)
verifying that room '1' exists...
+ http --check-status --verify=no GET https://118.178.125.107:4443/rooms/1
2. 请求server端创建广播
>>> creating Broadcaster...
+ http --check-status --verify=no POST https://118.178.125.107:4443/rooms/1/broadcasters id=fL4KvJdi908zgfcI6UgP3ryyqXtVFfS0 displayName=Broadcaster 'device:={"name": "FFmpeg"}'
3. 请求server端创建audio 传输
>>> creating mediasoup PlainTransport for producing audio...
++ http --check-status --verify=no POST https://118.178.125.107:4443/rooms/1/broadcasters/fL4KvJdi908zgfcI6UgP3ryyqXtVFfS0/transports type=plain comedia:=true rtcpMux:=false
ack:
res='{"id":"c871abab-1f47-4ddb-b3a7-0074733276a4","ip":"118.178.125.107","port":40001,"rtcpPort":40006}'
++ audioTransportId=c871abab-1f47-4ddb-b3a7-0074733276a4
++ audioTransportIp=118.178.125.107
++ audioTransportPort=40001
++ audioTransportRtcpPort=40006
4. 请求server端创建video 传输
>>> creating mediasoup PlainTransport for producing video...
++ http --check-status --verify=no POST https://118.178.125.107:4443/rooms/1/broadcasters/fL4KvJdi908zgfcI6UgP3ryyqXtVFfS0/transports type=plain comedia:=true rtcpMux:=false
ack:
+ res='{"id":"b3069d51-7a4b-406e-862d-b1356801fe8a","ip":"118.178.125.107","port":40002,"rtcpPort":40018}'
++ videoTransportId=b3069d51-7a4b-406e-862d-b1356801fe8a
++ videoTransportIp=118.178.125.107
++ videoTransportPort=40002
++ videoTransportRtcpPort=40018
5. 请求server端创建audio Producer
>>> creating mediasoup audio Producer...
+ http --check-status --verify=no -v POST https://118.178.125.107:4443/rooms/1/broadcasters/fL4KvJdi908zgfcI6UgP3ryyqXtVFfS0/transports/c871abab-1f47-4ddb-b3a7-0074733276a4/producers kind=audio 'rtpParameters:={ "codecs": [{ "mimeType":"audio/opus", "payloadType":100, "clockRate":48000, "channels":2, "parameters":{ "sprop-stereo":1 } }], "encodings": [{ "ssrc":1111 }] }'
6. 请求server端创建video Producer
>>> creating mediasoup video Producer...
+ http --check-status --verify=no -v POST https://118.178.125.107:4443/rooms/1/broadcasters/fL4KvJdi908zgfcI6UgP3ryyqXtVFfS0/transports/b3069d51-7a4b-406e-862d-b1356801fe8a/producers kind=video 'rtpParameters:={ "codecs": [{ "mimeType":"video/vp8", "payloadType":101, "clockRate":90000 }], "encodings": [{ "ssrc":2222 }] }'
7. 运行ffmpeg向server端 指定rtp端口发送rtp/rtsp数据
>>> running ffmpeg...
+ ffmpeg -re -v info -stream_loop -1 -i ./test.webM -map 0:a:0 -acodec copy -map 0:v:0 -c:v copy -f tee '[select=a:f=rtp:ssrc=1111:payload_type=100]rtp://118.178.125.107:40001?rtcpport=40006|[select=v:f=rtp:ssrc=2222:payload_type=101]rtp://118.178.125.107:40002?rtcpport=40018'
8. 程序退出的时候自动删除前边创建的broadcaster
+ http --check-status --verify=no DELETE https://118.178.125.107:4443/rooms/1/broadcasters/fL4KvJdi908zgfcI6UgP3ryyqXtVFfS0
遇到的问题:
./ffmpeg.sh
>>> verifying that room '1' exists...
http: error: SSLError: HTTPSConnectionPool(host='118.178.125.107', port=4443): Max retries exceeded with url: /rooms/1 (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)'),)) while doing GET request to URL: https://118.178.125.107:4443/rooms/1
解决:
HTTPIE_COMMAND="http --check-status --verify=no" 后边加上--verify=no 不校验Https
其他问题:
chrome 可以通过设置支持h264, 但是webrtc支持h264需要修改源码, 还是比较麻烦, 目前先能看到效果就好, 至于什么编码, 并不是最关心的, 当然后续上产品会修改代码并支持h264;