Files
王阳 be445f2899 阶段4:格式自动识别 + flv.js 替换为 mpegts.js + 移动端 5 项修复 + 自动化冒烟测试
- 按 URL 扩展名自动识别插件(.m3u8→hls.js,.flv/.ts/.m2ts→mpegts.js),iOS 上 m3u8 仍走原生 HLS
- flv 播放改由 mpegts.js 承担,移除 flv.js 依赖,plug:'flv.js' 保留兼容别名
- 修复 plug:'dash.js' 调用不存在函数的死代码 bug
- mpegts 能力判断由 mseLivePlayback 放宽为 isSupported()(修复部分浏览器点播被误杀)
- 移动端:iOS 原生全屏状态同步、iPad/iPod UA 识别、X5 同层播放属性、进度/音量条触摸拖动、触摸坐标滚动偏移修正
- 新增 Playwright 冒烟测试(npm test)与支持 Range 的本地服务器(npm run serve)
- 文档说明:测试禁用 python http.server(不支持 Range,mp4 无法 seek)
2026-07-21 16:43:51 +08:00

44 lines
1.8 KiB
JavaScript

/*
* 支持 Range 请求的静态文件服务器(测试用)
* python3 -m http.server 不支持 Range,会导致 mp4 无法 seek,故用此替代
* 用法:node scripts/serve.js [端口]
*/
const http = require('http');
const fs = require('fs');
const path = require('path');
const root = path.resolve(__dirname, '..');
const port = parseInt(process.argv[2] || '8931', 10);
const mime = {
'.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css',
'.png': 'image/png', '.mp4': 'video/mp4', '.json': 'application/json',
'.map': 'application/json', '.ico': 'image/x-icon'
};
http.createServer((req, res) => {
const urlPath = decodeURIComponent(req.url.split('?')[0]);
let file = path.join(root, urlPath === '/' ? 'index.html' : urlPath);
if (!file.startsWith(root)) { res.writeHead(403); res.end(); return; }
fs.stat(file, (err, stat) => {
if (err || !stat.isFile()) { res.writeHead(404); res.end('404'); return; }
const type = mime[path.extname(file).toLowerCase()] || 'application/octet-stream';
const range = req.headers.range;
if (range) {
const m = /bytes=(\d*)-(\d*)/.exec(range);
let start = m && m[1] ? parseInt(m[1], 10) : 0;
let end = m && m[2] ? parseInt(m[2], 10) : stat.size - 1;
end = Math.min(end, stat.size - 1);
res.writeHead(206, {
'Content-Type': type,
'Content-Range': `bytes ${start}-${end}/${stat.size}`,
'Accept-Ranges': 'bytes',
'Content-Length': end - start + 1
});
fs.createReadStream(file, { start, end }).pipe(res);
} else {
res.writeHead(200, { 'Content-Type': type, 'Accept-Ranges': 'bytes', 'Content-Length': stat.size });
fs.createReadStream(file).pipe(res);
}
});
}).listen(port, () => console.log(`静态服务器(支持 Range): http://localhost:${port}`));