node.js - 网络摄像头显示在 LAN 上而不是互联网

标签 node.js websocket ffmpeg webcam

好的,这不是因为一个愚蠢的错误:我已经转发了端口并且中间没有防火墙。
我尝试使 jsmpeg ( https://github.com/phoboslab/jsmpeg ) 的“实时流”部分在 Internet 上工作。为了在我的网页上获取网络摄像头流,我修改了“stream-server.js”

if( process.argv.length < 3 ) {
	console.log(
		'Usage: \n' +
		'node stream-server.js <secret> [<stream-port> <websocket-port>]'
	);
	process.exit();
}

var STREAM_SECRET = process.argv[2],
	STREAM_PORT = process.argv[3] || 8082,
	WEBSOCKET_PORT = process.argv[4] || 8084,
	STREAM_MAGIC_BYTES = 'jsmp'; // Must be 4 bytes

var width = 320,
	height = 240;

// Websocket Server
var socketServer = new (require('ws').Server)({port: WEBSOCKET_PORT});
socketServer.on('connection', function(socket) {
	// Send magic bytes and video size to the newly connected socket
	// struct { char magic[4]; unsigned short width, height;}
	var streamHeader = new Buffer(8);
	streamHeader.write(STREAM_MAGIC_BYTES);
	streamHeader.writeUInt16BE(width, 4);
	streamHeader.writeUInt16BE(height, 6);
	socket.send(streamHeader, {binary:true});

	console.log( 'New WebSocket Connection ('+socketServer.clients.length+' total)' );
	
	socket.on('close', function(code, message){
		console.log( 'Disconnected WebSocket ('+socketServer.clients.length+' total)' );
	});
});

socketServer.broadcast = function(data, opts) {
	for( var i in this.clients ) {
		if (this.clients[i].readyState == 1) {
			this.clients[i].send(data, opts);
		}
		else {
			console.log( 'Error: Client ('+i+') not connected.' );
		}
	}
};


// HTTP Server to accept incomming MPEG Stream
var streamServer = require('http').createServer( function(request, response) {
	var params = request.url.substr(1).split('/');

	if( params[0] == STREAM_SECRET ) {
		width = (params[1] || 320)|0;
		height = (params[2] || 240)|0;
		
		console.log(
			'Stream Connected: ' + request.socket.remoteAddress + 
			':' + request.socket.remotePort + ' size: ' + width + 'x' + height
		);
		request.on('data', function(data){
			socketServer.broadcast(data, {binary:true});
		});
	}
	else {
		console.log(
			'Failed Stream Connection: '+ request.socket.remoteAddress + 
			request.socket.remotePort + ' - wrong secret.'
		);
		response.end();
	}
}).listen(STREAM_PORT);

console.log('Listening for MPEG Stream on http://127.0.0.1:'+STREAM_PORT+'/<secret>/<width>/<height>');
console.log('Awaiting WebSocket connections on ws://127.0.0.1:'+WEBSOCKET_PORT+'/');

var servi = require('servi'),		// include the servi library
	app = new servi(false);		// servi instance

// configure the server's behavior:
app.port(8080);						// port number to run the server on
app.serveFiles("public");			// serve all static HTML files from /public
app.start();	
console.log("Listening for new clients on port 8080");
<!DOCTYPE html>
<html>
<head>
	<meta name="viewport" content="width=320, initial-scale=1"/>
	<title>jsmpeg streaming webcam</title>
	<style type="text/css">
		body {
			background: white;
			text-align: center;
			margin-top: 10%;
		}
		#videoCanvas {
			/* Always stretch the canvas to 640x480, regardless of its
			internal size. */
			width: 640px;
			height: 480px;
		}
	</style>
</head>
<body>
<h1>
 The Canvas size specified 
</h1>
	<!-- The Canvas size specified here is the "initial" internal resolution. jsmpeg will
		change this internal resolution to whatever the source provides. The size the
		canvas is displayed on the website is dictated by the CSS style.
	-->
	<canvas id="videoCanvas" width="640" height="480">
		<p>
			Please use a browser that supports the Canvas Element, like
			<a href="http://www.google.com/chrome">Chrome</a>,
			<a href="http://www.mozilla.com/firefox/">Firefox</a>,
			<a href="http://www.apple.com/safari/">Safari</a> or Internet Explorer 10
		</p>
	</canvas>
	<script type="text/javascript" src="jsmpg.js"></script>
	<script type="text/javascript">
		// Show loading notice
		var canvas = document.getElementById('videoCanvas');
		var ctx = canvas.getContext('2d');
		ctx.fillStyle = '#444';
		ctx.fillText('Loading...', canvas.width/2-30, canvas.height/3);

		// Setup the WebSocket connection and start the player
		var client = new WebSocket( 'ws://192.168.1.15:8084/' );
		var player = new jsmpeg(client, {canvas:canvas});
	</script>
</body>
</html>


“index.html”包含在“public”文件夹中。

然后我开始 ffmpeg:
`ffmpeg -s 640x480 -f video4linux2 -i /dev/video0 -f mpeg1video -b:v 800k -r 30 http://192.168.1.15:8082/1693/640/480/`

当我在局域网的任何站点上打开 url 192.168.1.x:8080 时,我会在我的页面“jsmpeg streaming webcam”上看到网络摄像头流式传输;但是如果从本地网络外部使用公共(public) ip 41.142.x.y:8080(使用 3G),我会得到页面(带有 h1 行“指定的 Canvas 大小”),但没有视频,它只是在“加载”框架中显示。
我不明白为什么它在本地而不是全局有效。为什么页面在互联网上流式传输,而不是网络摄像头?
谢谢你的帮助!

最佳答案

在客户端,你应该改变这个:

var client = 'ws://'+document.location.hostname+':8084/';
var player = new JSMpeg.Player(client, {canvas: canvas});

你这样做的方式是使用静态 IP 192.168.1.15。当它到达客户端时,他不知道这个ip是谁。

我还没有测试过,但我很确定 NAT 会转换 IP 地址......

关于node.js - 网络摄像头显示在 LAN 上而不是互联网,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30736301/

相关文章:

javascript - 在 25000 步中将更大的数字映射到 1-4

node.js - 通过 WebSocket 连接发送 HTML 是一种不好的做法吗

ffmpeg - Packet Corruption : Why sometimes ffmpeg . bat批量视频编辑让我的电脑不稳定无法重启?

javascript - Npm.require 找不到 Node 模块

node.js - 无法读取未定义的属性 'catch'

python - Websocket 握手状态 426

ruby-on-rails - 在heroku上使用回形针上传的视频没有屏幕,只有声音

visual-studio-2010 - 使用 opencv2 函数调试 Opencv 项目时出现错误的未知原因

node.js - 升级到 Nodejs 8 和 "error: failed to commit transaction"

node.js - 如何使用套接字(socket.io)在 NodeJS 中找到客户端的响应时间(延迟)?