NodeJS设备端音视频采集及React/React Native解码播放方案咨询
BeagleBone/Raspberry Pi Node.js 音视频流解决方案
a) Node.js 采集并转码音视频流
通过ffmpeg子进程直接调用硬件采集音视频,同时转码为多端兼容格式。先在设备上安装依赖工具:
# Raspberry Pi/BeagleBone 通用命令 sudo apt update && sudo apt install ffmpeg alsa-utils
安装Node.js依赖包:
npm install express fluent-ffmpeg ws
服务端代码(server.js):
const express = require('express'); const { spawn } = require('child_process'); const WebSocket = require('ws'); const http = require('http'); const app = express(); const PORT = 3000; const server = http.createServer(app); const wss = new WebSocket.Server({ server }); // 方案1:HLS流(兼容Web/React Native,延迟2-5秒) app.get('/stream.m3u8', (req, res) => { res.setHeader('Content-Type', 'application/vnd.apple.mpegurl'); const ffmpegArgs = [ '-f', 'v4l2', '-i', '/dev/video0', // 摄像头设备,用`v4l2-ctl --list-devices`确认路径 '-f', 'alsa', '-i', 'default', // 麦克风设备,用`arecord -l`确认设备名 '-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '28', '-tune', 'zerolatency', '-c:a', 'aac', '-b:a', '64k', '-f', 'hls', '-hls_time', '2', '-hls_list_size', '5', '-hls_flags', 'delete_segments', '-' ]; const ffmpegProc = spawn('ffmpeg', ffmpegArgs); ffmpegProc.stdout.pipe(res); req.on('close', () => ffmpegProc.kill()); ffmpegProc.on('exit', code => console.log(`ffmpeg exited with code ${code}`)); }); // 方案2:WebSocket实时流(延迟<1秒,低延迟场景) wss.on('connection', ws => { console.log('Client connected'); const ffmpegArgs = [ '-f', 'v4l2', '-i', '/dev/video0', '-f', 'alsa', '-i', 'default', '-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '30', '-tune', 'zerolatency', '-c:a', 'aac', '-b:a', '64k', '-f', 'mpegts', '-' ]; const ffmpegProc = spawn('ffmpeg', ffmpegArgs); ffmpegProc.stdout.on('data', data => { if (ws.readyState === WebSocket.OPEN) ws.send(data); }); ws.on('close', () => { ffmpegProc.kill(); console.log('Client disconnected'); }); }); server.listen(PORT, () => { const deviceIp = require('os').networkInterfaces().wlan0[0].address; console.log(`Server running at http://${deviceIp}:${PORT}`); });
b) 转成浏览器可播放格式
上述代码已完成格式转换:
- HLS流(
.m3u8):兼容所有现代浏览器、React Native、iOS/Android原生应用 - MPEG-TS流(WebSocket传输):适合低延迟场景,需客户端解码支持
c) React Native 解码播放
方案1:HLS流播放(简单易实现)
安装依赖:
npm install react-native-video # Expo项目使用:expo install expo-av
组件代码:
import React from 'react'; import { View, StyleSheet } from 'react-native'; import Video from 'react-native-video'; const CameraStream = () => { return ( <View style={styles.container}> <Video source={{ uri: 'http://你的设备IP:3000/stream.m3u8' }} style={styles.video} controls={true} muted={false} resizeMode="cover" onError={err => console.error('Video error:', err)} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#000' }, video: { flex: 1, width: '100%', height: '100%' } }); export default CameraStream;
d) React Web 解码播放
方案1:HLS流播放
使用react-player简化开发:
npm install react-player
组件代码:
import React from 'react'; import ReactPlayer from 'react-player'; const CameraStreamWeb = () => { return ( <div style={{ width: '100%', height: '100vh', backgroundColor: '#000' }}> <ReactPlayer url="http://你的设备IP:3000/stream.m3u8" playing={true} controls={true} width="100%" height="100%" onError={err => console.error('Playback error:', err)} /> </div> ); }; export default CameraStreamWeb;
方案2:WebSocket低延迟流
安装mpegts.js解码MPEG-TS流:
npm install mpegts.js
组件代码:
import React, { useEffect, useRef } from 'react'; import mpegts from 'mpegts.js'; const WebSocketStream = () => { const videoRef = useRef(null); useEffect(() => { if (!videoRef.current) return; const player = mpegts.createPlayer({ type: 'm2ts', url: 'ws://你的设备IP:3000' }); player.attachMediaElement(videoRef.current); player.load(); player.play(); return () => player.destroy(); }, []); return ( <div style={{ width: '100%', height: '100vh', backgroundColor: '#000' }}> <video ref={videoRef} controls autoPlay style={{ width: '100%', height: '100%' }} /> </div> ); }; export default WebSocketStream;
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

