React中HLS流媒体无法播放问题求助(树莓派4推流场景)
问题描述
我在树莓派4上搭建视频推流服务:用picamera2采集视频,通过内部集成的ffmpeg生成HLS流媒体的m3u8文件,再用http.server托管静态HLS文件。
用以下静态HTML测试时,推流可在其他设备正常播放:
<!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <title>Your title</title> <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet"> <script src="https://unpkg.com/video.js/dist/video.js"></script> <script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script> </head> <body> <video id="my_video_1" class="video-js vjs-fluid vjs-default-skin" controls preload="auto" data-setup='{}'> <source src="http://192.168.1.8:8000/live/stream.m3u8" type="application/x-mpegURL"> </video> <script> var player = videojs('my_video_1'); player.play(); </script> </body> </html>
但在React前端中无法正常加载该推流:用ReactPlayer编写的代码能播放在线HLS链接,但加载树莓派的推流时一直处于加载状态。也试过video.js、react-hls-player等库,ReactPlayer在兼容性上表现最优,但针对该推流仍无法工作。React代码如下:
import * as React from 'react'; import { useContext } from "react"; import Card from '@mui/material/Card'; import CardHeader from '@mui/material/CardHeader'; import CardContent from '@mui/material/CardContent'; import Avatar from '@mui/material/Avatar'; import { red } from '@mui/material/colors'; import VideoCameraBackIcon from '@mui/icons-material/VideoCameraBack'; import ReactPlayer from 'react-player/lazy' import { Typography } from '@mui/material'; // import { UserContext } from "./context/UserContext"; export default function VideoCard({ alerter }) { var url = "http://192.168.1.8:8000/live/stream.m3u8" return ( <Card sx={{ height: '820px' }} variant="outlined"> <CardHeader avatar={ <Avatar sx={{ bgcolor: red[500] }} > <VideoCameraBackIcon /> </Avatar> } title={<Typography component="div" variant="h6"> Video Stream </Typography>} subheader="from Camera" /> <CardContent> <div > <ReactPlayer playing url={url} controls={true} width="100%" height="100%" /> </div> </CardContent> </Card> ); }
解决方案
1. 解决跨域(CORS)问题
React开发服务器(通常是localhost:3000)和树莓派的http.server属于不同域名,默认情况下http.server不会返回CORS允许头,导致浏览器拦截请求。
替换默认的http.server,用自定义Python脚本添加CORS头:
from http.server import HTTPServer, SimpleHTTPRequestHandler class CORSRequestHandler(SimpleHTTPRequestHandler): def end_headers(self): self.send_header('Access-Control-Allow-Origin', '*') self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS') self.send_header('Access-Control-Allow-Headers', 'Content-Type') super().end_headers() if __name__ == '__main__': HTTPServer(('', 8000), CORSRequestHandler).serve_forever()
将该脚本保存为server.py,在HLS文件目录执行python server.py启动服务,替代原来的python -m http.server。
2. 优化HLS流的兼容性
调整picamera2的ffmpeg参数,确保生成的HLS流符合浏览器兼容标准:
- 设置较短的分片时长(比如2秒),降低加载延迟
- 限制分片列表长度,避免浏览器加载过多历史片段
- 使用H.264 baseline编码 profile,确保全浏览器支持
修改picamera2的录制配置:
from picamera2 import Picamera2 from picamera2.encoders import H264Encoder from picamera2.outputs import FfmpegOutput picam2 = Picamera2() # 配置视频参数,可根据需求调整分辨率 video_config = picam2.create_video_configuration(main={"size": (1280, 720)}) picam2.configure(video_config) encoder = H264Encoder(bitrate=1000000) # 调整码率适配网络 # 添加ffmpeg的HLS兼容参数 output = FfmpegOutput( 'live/stream.m3u8', audio=False, options={ 'hls_time': '2', 'hls_list_size': '5', 'hls_flags': 'delete_segments', 'vcodec': 'libx264', 'profile:v': 'baseline', 'preset': 'ultrafast' # 快速编码适配树莓派性能 } ) picam2.start_recording(encoder, output)
3. 调整ReactPlayer配置
强制ReactPlayer使用hls.js内核,并配置低延迟选项:
- 先安装依赖:
npm install hls.js - 修改ReactPlayer组件配置:
<ReactPlayer playing url={url} controls={true} width="100%" height="100%" config={{ file: { hlsOptions: { enableWorker: true, lowLatencyMode: true, maxBufferLength: 3 // 限制缓冲长度,降低延迟 } } }} />
4. 验证网络连通性
- 在React设备上执行
curl http://192.168.1.8:8000/live/stream.m3u8,确认能获取到m3u8文件内容 - 检查树莓派的8000端口是否开放,没有被防火墙拦截(树莓派默认无防火墙,若开启需添加规则)
- 确保React设备和树莓派在同一局域网网段内
内容的提问来源于stack exchange,提问作者Shashi Kumar Fagna
相关产品推荐
相关产品推荐

