init
This commit is contained in:
30
node_modules/node-rtsp-stream/Cakefile
generated
vendored
Normal file
30
node_modules/node-rtsp-stream/Cakefile
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{print} = require 'util'
|
||||
{spawn} = require 'child_process'
|
||||
|
||||
build = (watch) ->
|
||||
options = ['-c', '-o', 'lib', 'src']
|
||||
if watch is true
|
||||
options.unshift '-w'
|
||||
coffee = spawn 'coffee', options
|
||||
coffee.stderr.on 'data', (data) ->
|
||||
coffee = spawn 'node_modules\\.bin\\coffee.cmd', options
|
||||
coffee.stdout.on 'data', (data) ->
|
||||
console.log data.toString().trim()
|
||||
coffee.stderr.on 'data', (data) ->
|
||||
console.log data.toString().trim()
|
||||
coffee.on 'error', (error) ->
|
||||
coffee = spawn 'node_modules\\.bin\\coffee.cmd', options
|
||||
coffee.stdout.on 'data', (data) ->
|
||||
console.log data.toString().trim()
|
||||
coffee.stderr.on 'data', (data) ->
|
||||
console.log data.toString().trim()
|
||||
coffee.stdout.on 'data', (data) ->
|
||||
print data.toString()
|
||||
# coffee.on 'exit', (code) ->
|
||||
# callback?() if code is 0
|
||||
|
||||
task 'build', 'Build lib/ from src/', ->
|
||||
build false
|
||||
|
||||
task 'watch', 'Watch src/ for changes', ->
|
||||
build true
|
||||
22
node_modules/node-rtsp-stream/LICENSE
generated
vendored
Normal file
22
node_modules/node-rtsp-stream/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 David Jsa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
45
node_modules/node-rtsp-stream/README.md
generated
vendored
Normal file
45
node_modules/node-rtsp-stream/README.md
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
node-rtsp-stream
|
||||
================
|
||||
|
||||
Stream any RTSP stream and output to websocket for consumption by [jsmpeg](https://github.com/phoboslab/jsmpeg). HTML5 streaming video! (Requires ffmpeg)
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
$ npm install node-rtsp-stream
|
||||
```
|
||||
|
||||
On server:
|
||||
```
|
||||
Stream = require('node-rtsp-stream')
|
||||
stream = new Stream({
|
||||
name: 'name',
|
||||
streamUrl: 'rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov',
|
||||
wsPort: 9999,
|
||||
ffmpegOptions: { // options ffmpeg flags
|
||||
'-stats': '', // an option with no neccessary value uses a blank string
|
||||
'-r': 30 // options with required values specify the value after the key
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
On client:
|
||||
```
|
||||
<html>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript" src="jsmpeg.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
player = new JSMpeg.Player('ws://localhost:9999', {
|
||||
canvas: document.getElementById('canvas') // Canvas should be a canvas DOM element
|
||||
})
|
||||
</script>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more information on how to use jsmpeg to stream video, visit https://github.com/phoboslab/jsmpeg
|
||||
|
||||
Please note that framerate from cameras must be greater than or equal to 15fps for mpeg1 encoding, otherwise ffmpeg errors will prevent video encoding to occur. If you have a camera with advanced configuration options, make sure it streams video at a recommended 25fps.
|
||||
1
node_modules/node-rtsp-stream/index.js
generated
vendored
Normal file
1
node_modules/node-rtsp-stream/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./videoStream')
|
||||
56
node_modules/node-rtsp-stream/mpeg1muxer.js
generated
vendored
Normal file
56
node_modules/node-rtsp-stream/mpeg1muxer.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
var Mpeg1Muxer, child_process, events, util
|
||||
|
||||
child_process = require('child_process')
|
||||
|
||||
util = require('util')
|
||||
|
||||
events = require('events')
|
||||
|
||||
Mpeg1Muxer = function(options) {
|
||||
var key
|
||||
this.url = options.url
|
||||
this.ffmpegOptions = options.ffmpegOptions
|
||||
this.exitCode = undefined
|
||||
this.additionalFlags = []
|
||||
if (this.ffmpegOptions) {
|
||||
for (key in this.ffmpegOptions) {
|
||||
this.additionalFlags.push(key)
|
||||
if (String(this.ffmpegOptions[key]) !== '') {
|
||||
this.additionalFlags.push(String(this.ffmpegOptions[key]))
|
||||
}
|
||||
}
|
||||
}
|
||||
this.spawnOptions = [
|
||||
"-i",
|
||||
this.url,
|
||||
'-f',
|
||||
'mpegts',
|
||||
'-codec:v',
|
||||
'mpeg1video',
|
||||
// additional ffmpeg options go here
|
||||
...this.additionalFlags,
|
||||
'-'
|
||||
]
|
||||
this.stream = child_process.spawn(options.ffmpegPath, this.spawnOptions, {
|
||||
detached: false
|
||||
})
|
||||
this.inputStreamStarted = true
|
||||
this.stream.stdout.on('data', (data) => {
|
||||
return this.emit('mpeg1data', data)
|
||||
})
|
||||
this.stream.stderr.on('data', (data) => {
|
||||
return this.emit('ffmpegStderr', data)
|
||||
})
|
||||
this.stream.on('exit', (code, signal) => {
|
||||
if (code === 1) {
|
||||
console.error('RTSP stream exited with error')
|
||||
this.exitCode = 1
|
||||
return this.emit('exitWithError')
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
util.inherits(Mpeg1Muxer, events.EventEmitter)
|
||||
|
||||
module.exports = Mpeg1Muxer
|
||||
86
node_modules/node-rtsp-stream/package.json
generated
vendored
Normal file
86
node_modules/node-rtsp-stream/package.json
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"node-rtsp-stream@*",
|
||||
"/root/nodejs"
|
||||
]
|
||||
],
|
||||
"_from": "node-rtsp-stream@*",
|
||||
"_hasShrinkwrap": false,
|
||||
"_id": "node-rtsp-stream@0.0.9",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/node-rtsp-stream",
|
||||
"_nodeVersion": "10.15.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/node-rtsp-stream_0.0.9_1581518674104_0.9643932523651375"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "david.d.jsa@gmail.com",
|
||||
"name": "kyriesent"
|
||||
},
|
||||
"_npmVersion": "6.8.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "node-rtsp-stream",
|
||||
"raw": "node-rtsp-stream@*",
|
||||
"rawSpec": "*",
|
||||
"scope": null,
|
||||
"spec": "*",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/node-rtsp-stream/-/node-rtsp-stream-0.0.9.tgz",
|
||||
"_shasum": "f79abd27f72eeee44713cfc43b8d939ab2700b8b",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "node-rtsp-stream@*",
|
||||
"_where": "/root/nodejs",
|
||||
"author": {
|
||||
"email": "david@jsa.me",
|
||||
"name": "David Jsa"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/kyriesent/node-rtsp-stream/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": "^7.0.0"
|
||||
},
|
||||
"description": "node-rtsp-stream ================",
|
||||
"devDependencies": {
|
||||
"mocha": "^5.2.0"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"fileCount": 9,
|
||||
"integrity": "sha512-ynSkdHL4fuhctl1GeK890De7n8Dw+37D6IAZGrzsFSrd4TYho6neFQpMS1t0ZRDGsAegKh2p6kl1l9Vo3pJk8w==",
|
||||
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeRA9SCRA9TVsSAnZWagAA0LkP/R/N7lyxbaavA9C7loZZ\nDj/+P4c9S4ddEosup81wWNcerqCUqp4+5WWfxEHBfDIl1ffRQZz2+MUf1g5I\nSD6gQ4oo865vbsKHZLx8hjZ8u0HdGXa3ZzvcmjYbYRGeqHkcfqZFxUnJN36J\nsJDjTRSdSHKxf0xTSEdv2tz13ETOwYGHeOqka8dyM3P6AFG78bRBaKvTasB2\nlRaGRWVNpW9G+NHghs5U8ZJG1wNvhKli1EIwRIHZuruQmoS2GjzvW9DCfYE+\nZvh01DViEsH66DMI+CSNLHXmJ+8+c/X+Z5MCM0p0F2M4IkW04ZU3eC8ps4W3\noENvKm0lR6xzgLjIUPK7L1l8g95PRW/s+Zos/iUdLas0rXcDFTslNoCZ1gfe\nM9KoGQMHHas7nce4womwL4F8BVmuIrRhNuzSGderHv08epSskpYSRTin04Mp\ndS94XaiPIvkGCGn+xo9ApP4CE2wqvEmJaAYcsH4dQRfKl0lnQjXfpavAqCy+\n22a6smxF3BqOsi0yoVvS1zOg3aHBFWqdgY8zHwda7dvAkwvn5SrnekCEfh4w\n2pPWkrCWx2SjaNpT4cGtq23galaqcof+X72v6ho3/imvRqR+agpI3BSO0dpJ\niSCFo6wmbg+QJcu5M29g2uH4uV+h3iq06qR59DgAb8dX6kKIszBAq9hdvuiN\noYQN\r\n=LR+N\r\n-----END PGP SIGNATURE-----\r\n",
|
||||
"shasum": "f79abd27f72eeee44713cfc43b8d939ab2700b8b",
|
||||
"tarball": "https://registry.npmjs.org/node-rtsp-stream/-/node-rtsp-stream-0.0.9.tgz",
|
||||
"unpackedSize": 10349
|
||||
},
|
||||
"gitHead": "5fc1ff0e0ddafe7f0193ccd4a1fb0aa619450a7c",
|
||||
"homepage": "https://github.com/kyriesent/node-rtsp-stream#readme",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "kyriesent",
|
||||
"email": "david.d.jsa@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "node-rtsp-stream",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/kyriesent/node-rtsp-stream.git"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "npm run test",
|
||||
"test": "mocha test/*.js"
|
||||
},
|
||||
"version": "0.0.9"
|
||||
}
|
||||
11
node_modules/node-rtsp-stream/test.js
generated
vendored
Normal file
11
node_modules/node-rtsp-stream/test.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
Stream = require('./index')
|
||||
stream = new Stream({
|
||||
name: 'name',
|
||||
streamUrl: 'rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov',
|
||||
wsPort: 9999,
|
||||
ffmpegOptions: { // options ffmpeg flags
|
||||
'-stats': '', // an option with no neccessary value uses a blank string
|
||||
'-r': '30', // options with required values specify the value after the key
|
||||
'-s': '160x120',
|
||||
}
|
||||
})
|
||||
37
node_modules/node-rtsp-stream/test/tests.js
generated
vendored
Normal file
37
node_modules/node-rtsp-stream/test/tests.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// Generated by CoffeeScript 2.4.1
|
||||
(function() {
|
||||
var assert;
|
||||
|
||||
assert = require('assert');
|
||||
|
||||
describe('node-rstp-stream', function() {
|
||||
var VideoStream;
|
||||
VideoStream = require('../');
|
||||
return it('should not throw an error when instantiated', function(done) {
|
||||
var videoStream;
|
||||
videoStream = new VideoStream({
|
||||
name: 'wowza',
|
||||
streamUrl: 'rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov',
|
||||
wsPort: 9999,
|
||||
width: 240,
|
||||
height: 160,
|
||||
ffmpegOptions: {
|
||||
'-stats': '',
|
||||
'-r': '30'
|
||||
}
|
||||
});
|
||||
videoStream.on('exitWithError', () => {
|
||||
videoStream.stop();
|
||||
assert.fail('videoStream exited with error');
|
||||
return done();
|
||||
});
|
||||
// Must use setTimeout because we need the stream instantiated before we can stop it
|
||||
// otherwise it blocks the test runner from exiting.
|
||||
return setTimeout(() => {
|
||||
videoStream.stop();
|
||||
return done();
|
||||
}, 1900);
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
134
node_modules/node-rtsp-stream/videoStream.js
generated
vendored
Normal file
134
node_modules/node-rtsp-stream/videoStream.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
var Mpeg1Muxer, STREAM_MAGIC_BYTES, VideoStream, events, util, ws
|
||||
|
||||
ws = require('ws')
|
||||
|
||||
util = require('util')
|
||||
|
||||
events = require('events')
|
||||
|
||||
Mpeg1Muxer = require('./mpeg1muxer')
|
||||
|
||||
STREAM_MAGIC_BYTES = "jsmp" // Must be 4 bytes
|
||||
|
||||
VideoStream = function(options) {
|
||||
this.options = options
|
||||
this.name = options.name
|
||||
this.streamUrl = options.streamUrl
|
||||
this.width = options.width
|
||||
this.height = options.height
|
||||
this.wsPort = options.wsPort
|
||||
this.inputStreamStarted = false
|
||||
this.stream = undefined
|
||||
this.startMpeg1Stream()
|
||||
this.pipeStreamToSocketServer()
|
||||
return this
|
||||
}
|
||||
|
||||
util.inherits(VideoStream, events.EventEmitter)
|
||||
|
||||
VideoStream.prototype.stop = function() {
|
||||
this.wsServer.close()
|
||||
this.stream.kill()
|
||||
this.inputStreamStarted = false
|
||||
return this
|
||||
}
|
||||
|
||||
VideoStream.prototype.startMpeg1Stream = function() {
|
||||
var gettingInputData, gettingOutputData, inputData, outputData
|
||||
this.mpeg1Muxer = new Mpeg1Muxer({
|
||||
ffmpegOptions: this.options.ffmpegOptions,
|
||||
url: this.streamUrl,
|
||||
ffmpegPath: this.options.ffmpegPath == undefined ? "ffmpeg" : this.options.ffmpegPath
|
||||
})
|
||||
this.stream = this.mpeg1Muxer.stream
|
||||
if (this.inputStreamStarted) {
|
||||
return
|
||||
}
|
||||
this.mpeg1Muxer.on('mpeg1data', (data) => {
|
||||
return this.emit('camdata', data)
|
||||
})
|
||||
gettingInputData = false
|
||||
inputData = []
|
||||
gettingOutputData = false
|
||||
outputData = []
|
||||
this.mpeg1Muxer.on('ffmpegStderr', (data) => {
|
||||
var size
|
||||
data = data.toString()
|
||||
if (data.indexOf('Input #') !== -1) {
|
||||
gettingInputData = true
|
||||
}
|
||||
if (data.indexOf('Output #') !== -1) {
|
||||
gettingInputData = false
|
||||
gettingOutputData = true
|
||||
}
|
||||
if (data.indexOf('frame') === 0) {
|
||||
gettingOutputData = false
|
||||
}
|
||||
if (gettingInputData) {
|
||||
inputData.push(data.toString())
|
||||
size = data.match(/\d+x\d+/)
|
||||
if (size != null) {
|
||||
size = size[0].split('x')
|
||||
if (this.width == null) {
|
||||
this.width = parseInt(size[0], 10)
|
||||
}
|
||||
if (this.height == null) {
|
||||
return this.height = parseInt(size[1], 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpeg1Muxer.on('ffmpegStderr', function(data) {
|
||||
return global.process.stderr.write(data)
|
||||
})
|
||||
this.mpeg1Muxer.on('exitWithError', () => {
|
||||
return this.emit('exitWithError')
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
VideoStream.prototype.pipeStreamToSocketServer = function() {
|
||||
this.wsServer = new ws.Server({
|
||||
port: this.wsPort
|
||||
})
|
||||
this.wsServer.on("connection", (socket, request) => {
|
||||
return this.onSocketConnect(socket, request)
|
||||
})
|
||||
this.wsServer.broadcast = function(data, opts) {
|
||||
var results
|
||||
results = []
|
||||
for (let client of this.clients) {
|
||||
if (client.readyState === 1) {
|
||||
results.push(client.send(data, opts))
|
||||
} else {
|
||||
results.push(console.log("Error: Client from remoteAddress " + client.remoteAddress + " not connected."))
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
return this.on('camdata', (data) => {
|
||||
return this.wsServer.broadcast(data)
|
||||
})
|
||||
}
|
||||
|
||||
VideoStream.prototype.onSocketConnect = function(socket, request) {
|
||||
var streamHeader
|
||||
// Send magic bytes and video size to the newly connected socket
|
||||
// struct { char magic[4]; unsigned short width, height;}
|
||||
streamHeader = new Buffer(8)
|
||||
streamHeader.write(STREAM_MAGIC_BYTES)
|
||||
streamHeader.writeUInt16BE(this.width, 4)
|
||||
streamHeader.writeUInt16BE(this.height, 6)
|
||||
socket.send(streamHeader, {
|
||||
binary: true
|
||||
})
|
||||
console.log(`${this.name}: New WebSocket Connection (` + this.wsServer.clients.size + " total)")
|
||||
|
||||
socket.remoteAddress = request.connection.remoteAddress
|
||||
|
||||
return socket.on("close", (code, message) => {
|
||||
return console.log(`${this.name}: Disconnected WebSocket (` + this.wsServer.clients.size + " total)")
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = VideoStream
|
||||
Reference in New Issue
Block a user