-
-
Save leMedi/19c9955e1754810cdedeb9c325ae3e0b to your computer and use it in GitHub Desktop.
FFMPEG to Web Browser with Express, Socket.IO and JSMPEG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Shinobi (http://shinobi.video) - FFMPEG H.264 over HTTP Test | |
// How to Use raw H.264 (Simulated RTSP) | |
// 1. Start with `node ffmpegToWeb.js` | |
// 2. Get the IP address of the computer where you did step 1. Example : 127.0.0.1 | |
// 3. Open VLC and "Open Network Stream". | |
// 4. Input the following without quotes : `http://127.0.0.1:8001/h264` and start. | |
var child = require('child_process'); | |
var events = require('events'); | |
var express = require('express') | |
var app = express(); | |
var server = require('http').Server(app); | |
var io = require('socket.io')(server); | |
var spawn = child.spawn; | |
var exec = child.exec; | |
var Emitters = {} | |
var config = { | |
port:8001, | |
url:'rtsp://131.95.3.162/axis-media/media.3gp' | |
} | |
var initEmitter = function(feed){ | |
if(!Emitters[feed]){ | |
Emitters[feed] = new events.EventEmitter().setMaxListeners(0) | |
} | |
return Emitters[feed] | |
} | |
//web app | |
console.log('Starting Express Web Server on Port '+config.port) | |
server.listen(config.port); | |
app.get('/', function (req, res) { | |
res.sendFile(__dirname + '/index.html'); | |
}) | |
//ffmpeg pushed stream in here to make a pipe | |
app.all('/streamIn/:feed', function (req, res) { | |
req.Emitter = initEmitter(req.params.feed) | |
//req.params.feed = Feed Number (Pipe Number) | |
res.connection.setTimeout(0); | |
req.on('data', function(buffer){ | |
req.Emitter.emit('data',buffer) | |
io.to('STREAM_'+req.params.feed).emit('h264',{feed:req.params.feed,buffer:buffer}) | |
}); | |
req.on('end',function(){ | |
console.log('close'); | |
}); | |
}) | |
//socket.io client commands | |
io.on('connection', function (cn) { | |
cn.on('f',function (data) { | |
switch(data.function){ | |
case'getStream': | |
console.log(data) | |
cn.join('STREAM_'+data.feed) | |
break; | |
} | |
}) | |
}); | |
//simulate RTSP over HTTP | |
app.get(['/h264','/h264/:feed'], function (req, res) { | |
if(!req.params.feed){req.params.feed='1'} | |
req.Emitter = initEmitter(req.params.feed) | |
var contentWriter | |
var date = new Date(); | |
res.writeHead(200, { | |
'Date': date.toUTCString(), | |
'Connection': 'keep-alive', | |
'Cache-Control': 'no-cache', | |
'Pragma': 'no-cache', | |
'Content-Type': 'video/mp4', | |
'Server': 'Shinobi H.264 Test Stream', | |
}); | |
req.Emitter.on('data',contentWriter=function(buffer){ | |
res.write(buffer) | |
}) | |
res.on('close', function () { | |
req.Emitter.removeListener('data',contentWriter) | |
}) | |
}); | |
//ffmpeg | |
console.log('Starting FFMPEG') | |
var ffmpegString = '-i '+config.url+'' | |
ffmpegString += ' -f mpegts -c:v mpeg1video -an http://localhost:'+config.port+'/streamIn/1' | |
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(' ')); | |
ffmpeg.on('close', function (buffer) { | |
console.log('ffmpeg died') | |
}) | |
//ffmpeg.stderr.on('data', function (buffer) { | |
// console.log(buffer.toString()) | |
//}); | |
//ffmpeg.stdout.on('data', function (buffer) { | |
// Emitter.emit('data',buffer) | |
//}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="http://cdn.shinobi.video/js/socket.io.js"></script> | |
<script src="http://cdn.shinobi.video/js/jquery.min.js"></script> | |
<!--Special JSMPEG Start--> | |
<!--You need this version. Check for updates here https://github.com/ShinobiCCTV/jsmpeg-pipe --> | |
<script src="http://cdn.shinobi.video/js/jsmpeg.pipe.js"></script> | |
<!--Special JSMPEG End--> | |
<canvas id="canvas" height=500 width=500></canvas> | |
<script> | |
//start socket.io client connection | |
var socket = io(); | |
//on socket.io connection success | |
socket.on('connect',function(){ | |
//pretend this is the command you use to initiate getting H.264 (MPEG) data | |
socket.emit('f',{function:'getStream',feed:'2'}) | |
}) | |
// initiate a player that can be piped to. | |
var player = new JSMpeg.Player('pipe',{ | |
canvas:document.getElementById('canvas') | |
}); | |
//on data from "h264" handle | |
socket.on('h264', function (data) { | |
// `data.buffer` is the raw video data from FFMPEG | |
// pretend you are getting data as follows | |
// var data = {buffer:ArrayBuffer} | |
player.write(data.buffer) | |
}); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "ffmpegtoweb", | |
"version": "1.0.0", | |
"description": "Shinobi Testing Tool for H.264 over HTTP and Socket.IO", | |
"main": "ffmpegToWeb.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"dependencies": { | |
"express": "^4.14.0", | |
"socket.io": "^1.7.1" | |
}, | |
"author": "Moe Alam", | |
"license": "MIT" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment