FFmpeg:FIFO + PIPE
PIPE
var child = require('child_process');
var events = require('events');
var express = require('express')
var app = express();
var server = require('http').Server(app);
var spawn = child.spawn;
var exec = child.exec;
var Emitters = {}
var firstChunks = {}
var config = {
port:8001,
// url:'rtsp://131.95.3.162/axis-media/media.3gp'
url:'https://file-examples.com/storage/fe4b4c6261634c76e91986b/2017/04/file_example_MP4_480_1_5MG.mp4'
}
var initEmitter = function(feed){
if(!Emitters[feed]){
Emitters[feed] = new events.EventEmitter().setMaxListeners(0)
}
return Emitters[feed]
}
//hold first chunk of FLV video
var initFirstChunk = function(feed,firstBuffer){
if(!firstChunks[feed]){
firstChunks[feed] = firstBuffer
}
return firstChunks[feed]
}
console.log('Starting Express Web Server on Port '+config.port)
//start webserver
server.listen(config.port);
//make libraries static
app.use('/libs',express.static(__dirname + '/../../web/libs'));
app.use('/',express.static(__dirname + '/'));
//homepage with video element.
//static file send of index.html
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
})
//// FLV over HTTP, this URL goes in the flv.js javascript player
// see ./index.html
app.get(['/flv', '/flv/:feed/s.flv'], function (req, res) {
//default to first feed
if (!req.params.feed) { req.params.feed = '1' }
//get emitter
req.Emitter = initEmitter(req.params.feed)
//variable name of contentWriter
var contentWriter
//set headers
res.setHeader('Content-Type', 'video/x-flv');
res.setHeader('Access-Control-Allow-Origin', '*');
//write first frame on stream
// res.write(initFirstChunk(1))
//write new frames as they happen
//remove contentWriter when client leaves
res.on('close', function () {
console.log('客户端关闭连接');
ffmpeg.kill();
// req.Emitter.removeListener('data', contentWriter)
})
//ffmpeg
console.log('Starting FFMPEG')
var ffmpegString = '-re -stream_loop -1 -i ' + config.url + ' -c:v libx264 -an -f flv -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 pipe:1'
// var ffmpegString = '-re -stream_loop -1 -i '+config.url+' -c:v libx264 -an -f fifo -fifo_format flv -map 0:v -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 pipe:1'
//var ffmpegString = '-i '+config.url+' -c:v libx264 -preset superfast -tune zerolatency -c:a aac -ar 44100 -f flv pipe:4'
//ffmpegString += ' -f mpegts -c:v mpeg1video -an http://localhost:'+config.port+'/streamIn/2'
if (ffmpegString.indexOf('rtsp://') > -1) {
ffmpegString = '-rtsp_transport tcp ' + ffmpegString
}
console.log('Executing : ffmpeg ' + ffmpegString)
var ffmpeg = spawn('ffmpeg', ffmpegString.split(' '), { stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'] });
ffmpeg.on('close', function (buffer) {
console.log('ffmpeg died')
req.destroy();
});
//// FFMPEG Error Logs
//ffmpeg.stderr.on('data', function (buffer) {
// console.log(buffer.toString())
//});
//data from pipe:1 output of ffmpeg
ffmpeg.stdio[1].pipe(res);
ffmpeg.stdio[2].on('data', function (buffer) {
// initFirstChunk(1,buffer)
console.log(buffer.toString());
});
});
FIFO
将某些内容流式传输到stdout管道,即使在临时故障(网络中断)的情况下也继续以实时速率处理流,并尝试无限期地每秒恢复流式传输。
ffmpeg -re -stream_loop -1 -i https://file-examples.com/storage/fe4b4c6261634c76e91986b/2017/04/file_example_MP4_480_1_5MG.mp4 -c:v libx264 -an -f fifo -fifo_format flv -map 0 -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 pipe:1
通过 Node.js + express 将流发布为 http-flv :
var child = require('child_process');
var events = require('events');
var express = require('express')
var app = express();
var server = require('http').Server(app);
var spawn = child.spawn;
var exec = child.exec;
var Emitters = {}
var firstChunks = {}
var config = {
port:8001,
// url:'rtsp://131.95.3.162/axis-media/media.3gp'
url:'https://file-examples.com/storage/fe4b4c6261634c76e91986b/2017/04/file_example_MP4_480_1_5MG.mp4'
}
var initEmitter = function(feed){
if(!Emitters[feed]){
Emitters[feed] = new events.EventEmitter().setMaxListeners(0)
}
return Emitters[feed]
}
//hold first chunk of FLV video
var initFirstChunk = function(feed,firstBuffer){
if(!firstChunks[feed]){
firstChunks[feed] = firstBuffer
}
return firstChunks[feed]
}
console.log('Starting Express Web Server on Port '+config.port)
//start webserver
server.listen(config.port);
//make libraries static
app.use('/libs',express.static(__dirname + '/../../web/libs'));
app.use('/',express.static(__dirname + '/'));
//homepage with video element.
//static file send of index.html
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
})
//// FLV over HTTP, this URL goes in the flv.js javascript player
// see ./index.html
app.get(['/flv','/flv/:feed/s.flv'], function (req, res) {
//default to first feed
if(!req.params.feed){req.params.feed='1'}
//get emitter
req.Emitter = initEmitter(req.params.feed)
//variable name of contentWriter
var contentWriter
//set headers
res.setHeader('Content-Type', 'video/x-flv');
res.setHeader('Access-Control-Allow-Origin','*');
//write first frame on stream
// res.write(initFirstChunk(1))
//write new frames as they happen
req.Emitter.on('data',contentWriter=function(buffer){
res.write(buffer)
})
//remove contentWriter when client leaves
res.on('close', function () {
req.Emitter.removeListener('data',contentWriter)
})
});
//ffmpeg
console.log('Starting FFMPEG')
// var ffmpegString = '-re -stream_loop -1 -i '+config.url+' -c:v libx264 -an -f fifo -fifo_format flv -map 0:v -map 0:a -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 pipe:1'
var ffmpegString = '-re -stream_loop -1 -i '+config.url+' -c:v libx264 -an -f fifo -fifo_format flv -map 0 -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 pipe:1'
//var ffmpegString = '-i '+config.url+' -c:v libx264 -preset superfast -tune zerolatency -c:a aac -ar 44100 -f flv pipe:4'
//ffmpegString += ' -f mpegts -c:v mpeg1video -an http://localhost:'+config.port+'/streamIn/2'
if(ffmpegString.indexOf('rtsp://')>-1){
ffmpegString='-rtsp_transport tcp '+ffmpegString
}
console.log('Executing : ffmpeg '+ffmpegString)
var ffmpeg = spawn('ffmpeg',ffmpegString.split(' '),{stdio:['pipe','pipe','pipe','pipe','pipe']});
ffmpeg.on('close', function (buffer) {
console.log('ffmpeg died')
})
//// FFMPEG Error Logs
//ffmpeg.stderr.on('data', function (buffer) {
// console.log(buffer.toString())
//});
//data from pipe:1 output of ffmpeg
ffmpeg.stdio[1].on('data', function (buffer) {
// initFirstChunk(1,buffer)
initEmitter(1).emit('data',buffer)
});