如何解决ExpressJS 视频流有烦人的音频问题
我一直在尝试运行一个 Expressjs Web 服务器,该服务器从我的文件系统中提供视频。出于某种原因,每当播放视频时,都会有不断的爆裂声,最终(3-10 分钟后)音频完全中断。重新加载页面将恢复音频,但不会停止弹出。
我有 2 种不同的视频播放方法,但在运行时只使用了 1 种方法。它们都用于此功能:
app.get(`/${VIDTYPE}/:path`,(req,res) => {
let p = decode(req.params.path)
let dir = path.dirname(p)
let name = path.parse(p).name
let ext = '.vtt'
let track = path.resolve(`${dir}/${name}${ext}`)
console.log({track})
res.send(
`<video id="videoplayer" controls width="90%" height="90%">` +
`<source src="/video/${req.params.path}"/>` +
`<track default kind="subtitles" label="en" src="/track/${encode(track)}"/>` +
`</video>`
)
})
第一种方法是从网上抄来的,感觉比较复杂。
app.get("/video/:path",res) => {
let decoded = decode(req.params.path)
console.log("video",{decoded})
let stat = fs.statSync(decoded)
let fileSize = stat.size
let range = req.headers.range
if (range) {
const parts = range.replace(/bytes=/,"").split("-")
const start = parseInt(parts[0],10)
const end = parts[1]
? parseInt(parts[1],10)
: fileSize-1
const chunksize = (end-start)+1
const file = fs.createReadStream(decoded,{start,end})
const head = {
'Content-Range': `bytes ${start}-${end}/${fileSize}`,'Accept-Ranges': 'bytes','Content-Length': chunksize,'Content-Type': 'video/mp4',}
res.writeHead(206,head);
file.pipe(res);
} else {
const head = {
'Content-Length': fileSize,}
res.writeHead(200,head)
fs.createReadStream(path).pipe(res)
}
})
第二种方法要简单得多,而且功能似乎相同。它们都存在音频问题,但质量没有明显差异。
app.get("/video2/:path",res) => {
res.sendFile(decode(req.params.path))
})
完整的代码库将在评论中。所有 mp4 文件都是使用 ffmpeg 从 mkv 转换而来的,因此这可能会导致问题,但在直接播放时,没有一个视频具有相同的音频问题。我也将问题隔离到移动设备上。
对我哪里出错有什么想法吗?
解决方法
代码库:
const { json } = require('body-parser')
const { dir } = require('console')
const { response } = require('express')
const express = require('express')
const fs = require("fs")
const path = require("path")
const port = 80
const app = express()
const vid_ext = [
'.mp4','.webm'
]
const VIDTYPE = "vid"
const DIRTYPE = "dir"
const getAllFiles = function(dirPath) {
console.log({dirPath});
files = fs.readdirSync(dirPath)
arrayOfFiles = [{
path: path.join(dirPath + "/.."),title: "go up(beta)",type: DIRTYPE
}]
files.forEach(function(file) {
let p = path.resolve(path.join(dirPath,"/",file))
if (fs.statSync(dirPath + "/" + file).isDirectory()) {
arrayOfFiles.push({
path: p,title: file,type: DIRTYPE
})
} else {
if (vid_ext.includes(path.extname(p))) {
arrayOfFiles.push({
path: p,type: VIDTYPE
})
}
}
})
return arrayOfFiles
}
app.get('/',(request,response) => {
response.redirect(`/${DIRTYPE}/${encode("../stuff")}`);
});
app.get(`/${DIRTYPE}/:path`,(req,res) => {
let decoded = decode(req.params.path)
console.log(DIRTYPE,decoded)
res.send(dirtable(decoded))
})
app.get("/video/:path",res) => {
let decoded = decode(req.params.path)
console.log("video",{decoded})
let stat = fs.statSync(decoded)
let fileSize = stat.size
let range = req.headers.range
if (range) {
const parts = range.replace(/bytes=/,"").split("-")
const start = parseInt(parts[0],10)
const end = parts[1]
? parseInt(parts[1],10)
: fileSize-1
const chunksize = (end-start)+1
const file = fs.createReadStream(decoded,{start,end})
const head = {
'Content-Range': `bytes ${start}-${end}/${fileSize}`,'Accept-Ranges': 'bytes','Content-Length': chunksize,'Content-Type': 'video/mp4',}
res.writeHead(206,head);
file.pipe(res);
} else {
const head = {
'Content-Length': fileSize,}
res.writeHead(200,head)
fs.createReadStream(path).pipe(res)
}
})
app.get("/video2/:path",res) => {
res.sendFile(decode(req.params.path))
})
app.get(`/${VIDTYPE}/:path`,res) => {
let p = decode(req.params.path)
let dir = path.dirname(p)
let name = path.parse(p).name
let ext = '.vtt'
let track = path.resolve(`${dir}/${name}${ext}`)
console.log({track})
res.send(
`<video id="videoplayer" controls width="90%" height="90%">` +
`<source src="/video/${req.params.path}"/>` +
`<track default kind="subtitles" label="en" src="/track/${encode(track)}"/>` +
`</video>`
)
//res.redirect(`/video2/${req.params.path}`)
})
app.get("/track/:path",res) => {
res.sendFile(decode(req.params.path))
})
function dirtable(a) {
let files = getAllFiles(a)
return (
"<table><tbody>" +
files.map(x => `<td>${linkfrom(x)}</td><td>${x.type}</td>`).reduce((acc,x) => acc + `<tr>${x}</tr>`) +
"</tbody></table>"
)
}
function linkfrom(a) {
return `<a href="/${a.type}/${encode(a.path)}">${a.title}</a>`
}
function encode(h) {
return Buffer.from(h).toString('base64')
}
function decode(h) {
return Buffer.from(h,"base64").toString()
}
app.listen(port,console.log(`App Listening to port ${port}`));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。