new MediaSource()
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'frag_bunny.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream();
video.play();
//console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
来自:https://developer.mozilla.org/zh-CN/docs/Web/API/MediaSource
参考:https://www.jianshu.com/p/1bfe4470349b
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
参照表:https://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support
方法
从父接口EventTarget上继承而来。
MediaSource.addSourceBuffer()
创建一个带有给定MIME类型的新的 SourceBuffer 并添加到 MediaSource 的 SourceBuffers 列表。
MediaSource.removeSourceBuffer() (en-US)
删除指定的SourceBuffer 从这个MediaSource对象中的 SourceBuffers列表。
MediaSource.endOfStream()
属性
MediaSource.sourceBuffers (en-US) 只读
返回一个SourceBufferList (en-US) 对象,包含了这个MediaSource的SourceBuffer的对象列表。
MediaSource.activeSourceBuffers (en-US) 只读
返回一个 SourceBufferList (en-US) 对象,包含了这个MediaSource.sourceBuffers (en-US)中的SourceBuffer 子集的对象—即提供当前被选中的视频轨 (video track),启用的音频轨 (audio tracks) 以及显示/隐藏的字幕轨 (text tracks) 的对象列表。
MediaSource.readyState 只读
返回一个包含当前MediaSource状态的集合,即使它当前没有附着到一个media元素(closed),或者已附着并准备接收SourceBuffer 对象 (open),亦或者已附着但这个流已被MediaSource.endOfStream()关闭(ended.)
MediaSource.duration
获取和设置当前正在推流媒体的持续时间。
流媒体处理
<div class="a">
<video id="video" controls preload="auto"></video>
</div>
<script>
$(function() {
var video = document.querySelector('#video');
var mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
function sourceOpen(e) {
URL.revokeObjectURL(video.src);
// 设置 媒体的编码类型
var mime = 'video/webm; codecs="vorbis,vp8"';
var mediaSource = e.target;
var sourceBuffer = mediaSource.addSourceBuffer(mime);
var videoUrl = 'http://localhost:9090/examples/mp4/video.webm';
fetch(videoUrl).then(function(response) {
console.log(response)
return response.arrayBuffer();
})
.then(function(arrayBuffer) {
sourceBuffer.addEventListener('updateend', function(e) {
if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
mediaSource.endOfStream();
// 在数据请求完成后,我们需要调用 endOfStream()。它会改变 MediaSource.readyState 为 ended 并且触发 sourceended 事件。
video.play().then(function() {}).catch(function(err) {
console.log(err)
});
}
});
sourceBuffer.appendBuffer(arrayBuffer);
});
}
})
</script>
参考:https://www.cnblogs.com/dh-dh/p/9254172.html
**视频分段加密: https://blog.csdn.net/camike/article/details/82797768
参考:https://blog.csdn.net/panqisheng/article/details/51470624
getvideosource () {
let cid = this.$route.query.chapterId
let path = 'http://localhost:3000/api/chapter/learning/video'
let mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
// let video = this.$refs.v1
let video = document.getElementById('v1')
let mediaSource
let that = this
if('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
console.log('MediaSource')
mediaSource = new MediaSource()
video.src = URL.createObjectURL(mediaSource)
mediaSource.addEventListener('sourceopen',sourceOpen.bind(this))
} else{
console.error('Unsupported MIME type or codec:',mimeCodec)
}
function sourceOpen () {
console.log('has opened')
URL.revokeObjectURL(video.src)
let sourceBuffer = mediaSource.addSourceBuffer(mimeCodec)
fetchAB(path,sourceBuffer)
}
function fetchAB (url,sourceBuffer) {
axios.get(url).then((result)=>{
console.log(Object.prototype.toString.call(result.data));
// console.log(result.data);
// let data = new Blob([result.data],{type: 'application/octet-stream'})
// console.log(Object.prototype.toString.call(data));
// console.log(data);
// var reader = new FileReader();
// reader.onload = function() {
// console.log(this.result);
// }
// reader.readAsArrayBuffer(blob);
function toArrayBuffer(buf) {
var ab = new ArrayBuffer(buf.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
view[i] = buf[i];
}
return ab;
}
let r = toArrayBuffer(result.data)
console.log(Object.prototype.toString.call(r))
sourceBuffer.addEventListener('updateend', function () {
console.log(mediaSource.readyState);
console.log(sourceBuffer)
console.log(mediaSource);
mediaSource.endOfStream()
})
sourceBuffer.appendBuffer(r)
})
}
},
node后台
router.get('/GetStream', function(req, res, next) {
let filePath = 'public/videos/frag_bunny.mp4'
res.set('Content-Type', 'application/octet-stream');
fs.createReadStream(filePath).pipe(res)
})
前端代码
export default {
data() {
return {
mediaSource: null,
sourceBuffer: null,
mimeType: 'video/mp4;codecs="avc1.42E01E,mp4a.40.2"'
}
},
mounted() {
// MediaSource.isTypeSupported('video/webm;codecs="vorbis,vp8"');//是否支持webm
// MediaSource.isTypeSupported('video/mp4;codecs="avc1.42E01E,mp4a.40.2"')//是否支持MP4
// MediaSource.isTypeSupported('video/mp2t;codes="avc1.42E01E,mp4a.40.2"')//是否支持ts
// 首先判断一下对视频格式的支持度,MediaSource提供了isTypeSupported方法
if ('MediaSource' in window && MediaSource.isTypeSupported(this.mimeType)) {
this.createMediaSource()
} else {
this.$message({message: '您的浏览器不支持MediaSource', type: 'warning'})
}
},
methods: {
createMediaSource() {
// 创建MediaSource对象,并使用URL.createObjectURL来创建指向MediaSource对象的URL供video播放
this.mediaSource = new MediaSource()
this.$refs.h5video.src = window.URL.createObjectURL(this.mediaSource)
// 监听sourceopen
this.mediaSource.addEventListener('sourceopen', this.onSourceOpen)
},
onSourceOpen() {
let self = this
// 创建一个新的 SourceBuffer 对象,然后会将它追加到 MediaSource 的 SourceBuffers 列表中。
this.sourceBuffer = this.mediaSource.addSourceBuffer(this.mimeType)
// 监听buffer更新结束事件
this.sourceBuffer.addEventListener('updateend', () => {
// 停止stream
self.mediaSource.endOfStream()
// 开始播放
self.$refs.h5video.play()
})
this.requestBuffer()
},
requestBuffer() {
let self = this
// 请求接口去拉流
this.$http.get('GetStream', null, {responseType: 'arraybuffer'}).then(resp => {
// 拉到的流塞进sourceBuffer里。
self.sourceBuffer.appendBuffer(resp)
})
}
}
}