需求
一、場景
用戶多家門店有監控探頭,設備是海康的和大華的。用戶總部和門店不在一個網絡下,並且總部要能實時調用查看門店監控,和門店回放畫面。我們知道監控攝像機獲取的視頻是 rtsp 流的格式。 只能在特用的軟件中播放,並且只能在相同的網絡下播放。用戶要求開發一個管理軟件根據業務需要來播放視頻。最終的目地是要把rtsp 流視頻 轉換為能在瀏覽器,手機等主流的播放渠道上能播放的視頻(rtmp,mp4,flv,m3u8等格式);
解決辦法
(1)、客戶端轉碼
我們用electron 來打包客戶端,客戶端中安裝一個在線轉碼ffmpeg 模塊,這個模塊中有功能接口能直接對rtsp 進行轉碼(這種場景主要給 播放軟件和門店在一個網絡下能直接連接的場景);
用到兩個模塊 “fluent-ffmpeg” “node-media-server”
fluent-ffmpeg 轉碼模塊
我們用這個模塊轉碼為rtmp 直播流,轉碼后推送到一個我們在軟件內部搭建的一個rtmp 直播流服務器地址
“rtmp://localhost:1938/live/livestream”
node-media-server 模塊做rtmp直播流服務器
上面的fluent-ffmpeg 模塊轉碼推送rtmp 流到這個服務器rtmp://localhost:1938/live/livestream,
到此rtsp被本地轉換為了 rtmp流了。 由於rtmp流可以在瀏覽器中播放, 我們找一個播放器播放這個地址即可。 能播放rtmp流的播放器很多。 我用了一個阿里的flash 播放器來播放可行。
# electron main.js 部分功能代碼
const ffmpeg = require('fluent-ffmpeg');
const { NodeMediaServer } = require('node-media-server');
// rtmp 播放 服務器
const config = {
rtmp: {
port: 1938,
chunk_size: 60000,
gop_cache: true,
ping: 60,
ping_timeout: 30
},
http: {
port: 8000,
allow_origin: '*'
}
};
var nms = new NodeMediaServer(config)
nms.run();
// 轉碼指令
var command = ffmpeg(uri)
.outputOptions([
'-fflags',
'nobuffer',
'-vcodec',
'libx264',
'-preset',
'superfast',
'-rtsp_transport',
'tcp',
'-threads',
'2',
// '-f',
// 'flv',
'-r',
'25',
// '-s',
// '640x480',
//'1280x720',
'-an'
])
.inputFPS(25)
.noAudio()
.size('640x?')
.aspect('4:3')
.format('flv')
// 此處的 /live/camera, camera類似於一個房間的概念, 你可以設置為你想要的名字
.save(`rtmp://localhost:1938/live/livestream`)
.on('start', function (e) {
running = true
console.log('stream is start: ' + e)
})
.on('end', function () {
running = false
console.log('ffmpeg is end')
})
.on('error', function (err) {
running = true
console.log('ffmpeg is error! ' + err)
//command.kill()
//reloadStream(uri)
})
(2)、服務器端轉碼
另一種轉碼是在外部服務器端安裝一套轉碼服務器,業務中發送接口到遠程服務器,服務器收到指令后“主動去拉取rtmp流進行轉碼”,轉碼后 再 推送到 服務器上的另外一個 rtmp 服務器上進行分發 rtmp 流;
1.轉碼服務器
我們用一個docker 容器來跑轉碼服務;
docker pull ranmufei/srs-php5-transcode-server:v1.18
容器中封裝了一個FFmpeg + web服務器 http://127.0.0.1//runffmpeg.php?type=run; post 提交參數
rtsp地址
curl -X POST \
http://xxxx.cn/admin/Index/testrunffmpeg \
-H 'cache-control: no-cache' \
-H 'content-type: application/x-www-form-urlencoded' \
-H 'postman-token: 148e4b67-1e03-f854-5c71-b1fc6502210c' \
-H 'token: 667778c46b900c9768c65ac7ce8102d9' \
-d rtsp=rtsp%3A%2F%2Fadmin%3Aadmin123%4010.31.37.50%3A554%2Fcam%2Frealmonitor%3Fchannel%3D1%26subtype%3D1
轉碼服務器放回 播rtmp 播放地址
放回格式json
{
"response": {
"ipinfo": {
"pid": null,
"ipinfo": null,
"command": null
},
"pid": "31199",
"playurl": "rtmp://srs-docker-rmf.bubugao:1935/live/livestream_1547693691",
"str": "/srs/objs/ffmpeg/bin/ffmpeg -rtsp_transport tcp -re -i 'rtsp://admin:xxxxx@10.31.37.50:554/cam/realmonitor?channel=1&subtype=1' -c:a copy -c:v libx264 -preset ultrafast -b:v 200k -r 8 -s 640x480 -f flv rtmp://srs-docker-rmf.bubugao:1935/live/livestream_1547693691 > /dev/null 2>&1 & echo $!;",
"rtsp": "rtsp://admin:xxxx@10.31.37.50:554/cam/realmonitor?channel=1&subtype=1",
"playpath": "rtmp://transcode.xxxxxx.cn:1935/live/livestream_1547693691",
"datainfo": {
"type": "run",
"rtsp": "rtsp://admin:xxxxx@10.31.37.50:554/cam/realmonitor?channel=1&subtype=1"
}
},
"status": 200,
"API_debug": {
"url": "transcode.video//runffmpeg.php?type=run",
"data": {
"type": "run",
"rtsp": "rtsp://admin:xxxx@10.31.37.50:554/cam/realmonitor?channel=1&subtype=1"
}
}
}
2.rtmp 分發流服務器
和第一中方式類似,也是拉取rtsp 地址 進行轉碼 ,這是轉碼后推送到了雲上的這台rtmp 流分發服務器上來了;
docker pull ossrs/srs:3.0.42-ffmpeg
配置服務器作為 rtmp 服務器; srs 的功能很強大,目前我們只用到了它的分發rtmp 流功能;
配置參考 https://github.com/ossrs/srs/wiki/v2_CN_Home
分發為m3u8 格式 供移動端播放
# srs 的docker.conf 配置中添加hls 配置 會生成 m3u8 的文件,當有流推送到 srs 服務器的時候 會自動高轉換為 m3u8 格式文件。
vhost __defaultVhost__ {
hls {
enabled on;
hls_path ./objs/nginx/html;
hls_fragment 10;
hls_window 60;
}
}