Express搭建HLS流服务:浏览器可访问但播放器报片段加载错误
解决Express+HLS播放时TS片段404的问题
你的核心问题是HLS清单(m3u8)中的TS片段路径解析错误,加上Express未配置对应路由返回TS文件,导致播放器请求错误路径的文件返回404。以下是具体分析和修复方案:
问题原因拆解
- 播放器请求
/cameras/cam1拿到m3u8后,会把里面的TS片段路径(如index133.ts)解析为相对于当前请求路径的父路径,也就是/cameras/index133.ts,但你的TS文件实际存在./cameras/cam1/目录下,路径不匹配。 - Express当前只配置了
/cameras/cam1的路由,没有处理TS文件的请求,所以任何/cameras/*.ts的请求都会返回404。
具体修复步骤
1. 配置Express静态文件服务,让TS文件可被正确请求
在index.js中添加静态文件服务,将本地./cameras目录映射到/cameras路由下,这样Express会自动处理TS文件的请求:
// 在app.use("/cameras", cameras);之前添加 app.use("/cameras", express.static("./cameras"));
添加后,请求/cameras/cam1/index133.ts时,Express会自动返回./cameras/cam1/index133.ts文件。
2. 修正m3u8中的TS片段路径
打开./cameras/cam1/index.m3u8,把里面的TS片段路径从indexxxx.ts改成cam1/indexxxx.ts,播放器会自动请求正确路径/cameras/cam1/indexxxx.ts。
如果是用FFmpeg生成HLS流,可直接在命令中添加hls_base_url参数指定基础路径,避免手动修改m3u8:
ffmpeg -i rtsp://你的RTSP地址 -c:v h264 -c:a aac -hls_time 2 -hls_list_size 5 -hls_base_url "/cameras/cam1/" -f hls ./cameras/cam1/index.m3u8
3. 优化m3u8请求的响应逻辑
在cameras.js中,设置HLS标准响应头,并用流读取文件(避免大文件占用内存):
const express = require("express"); const router = express.Router(); const fs = require("fs"); const path = require("path"); // 用绝对路径避免环境差异 const camOneStream = path.resolve(__dirname, "../cameras/cam1/index.m3u8"); router.get("/cam1", (req, res) => { console.log('Request Incoming for CAM1 from...', new Date()); // 设置HLS标准响应头,已通过全局cors处理跨域,无需重复设置 res.set({ 'Content-Type': 'application/vnd.apple.mpegurl', 'Access-Control-Allow-Headers': 'Range', 'Access-Control-Expose-Headers': 'Content-Length, Content-Range' }); // 流式读取文件,适合大文件场景 const stream = fs.createReadStream(camOneStream); stream.on('error', (err) => { console.error(err); res.status(500).send(`Server error: ${err.code}`); }); stream.pipe(res); }); module.exports = router;
额外优化建议
- 用
path.resolve处理文件路径,避免相对路径在不同运行环境下的异常。 - 实时转码RTSP流时,用
child_process.spawn代替exec,能更好地处理进程输出和错误,避免缓冲区溢出。 - 可给FFmpeg添加
hls_delete_threshold参数,自动删除旧的TS片段,避免磁盘空间被占满。
学习资源建议
- 先掌握HLS基本原理:HLS通过将视频分割为小TS片段,用m3u8清单管理片段,播放器通过请求清单和片段实现流式播放。
- 熟悉Express静态文件服务用法:了解如何映射本地目录到路由,处理静态资源请求。
- 学习FFmpeg转HLS核心参数:
hls_time(片段时长)、hls_list_size(保留片段数量)、hls_flags(如delete_segments自动删片段)等。
内容的提问来源于stack exchange,提问作者Akonfan
相关产品推荐
相关产品推荐

