为了解释这个问题,用node写个简单例子
以下是server.js,同目录下还有个1.mp4
浏览器访问:http://localhost:3000,
const {createServer:server}=require('http')
const url=require('url')
const fs=require('fs')
const mp4Path='./1.mp4'
server((req,res)=>{
let pathname=url.parse(req.url).pathname
if(pathname==='/'){
res.writeHead(200,{'Content-Type':'text/html'})
res.end(``)
return
}
if(pathname==='/1.mp4'){
res.writeHead(200,{'Content-Type':'video/mp4'})
fs.createReadStream(mp4Path).pipe(res)
return
}
res.end()
}).listen(3000,()=>{
console.log(`server listen on 3000`)
})
chrome正常播放,而苹果手机不能播放
我们打印下请求头,可以看到: range: 'bytes=0-1',
if(pathname==='/1.mp4'){
console.log(req.headers)
res.writeHead(200,{'Content-Type':'video/mp4'})
fs.createReadStream(mp4Path).pipe(res)
return
}
也就是说safari遇到mp4格式,第一次会请求文件的0-1个字节,这里写个函数getRange来获取
range字段的开始结束
const {createServer:server}=require('http')
const url=require('url')
const fs=require('fs')
const mp4Path='./1.mp4'
server((req,res)=>{
let pathname=url.parse(req.url).pathname
if(pathname==='/'){
res.writeHead(200,{'Content-Type':'text/html'})
res.end(``)
return
}
if(pathname==='/1.mp4'){
fs.stat('./1.mp4',(err,stats)=>{
let [start,end]=getRange(req.headers['range'],stats)
res.setHeader('Content-Range',`bytes ${start}-${end}/${stats.size}`)
res.setHeader('Content-Type','video/mp4')
res.setHeader('Content-Length',end==start?0:end-start+1)
res.writeHead(206)
fs.createReadStream(mp4Path,{
start:start,
end:end
}).pipe(res)
})
return
}
res.end()
}).listen(3000,()=>{
console.log(`server listen on 3000`)
})
function getRange(range,stats){
var r=range.match(/=(\d+)-(\d+)?/)
var start=r[1]
var end=r[2]||stats.size-1
return [parseInt(start),parseInt(end)];
}