mse
最近对于blob这个东西真的是很感兴趣,图片可以是blob,视频可以是blob,直播也可以是blob,感觉很厉害啊。与之紧密联系的MSE(Media Source Extensions)这个概念。研究一波。
Media Source Extensions 允许javaScript动态地为<audio>和<video>创建媒体流,而不再只能是引用一个视频文件的url。这样就极大地丰富了前端对音视频的处理能力,也赋予了其更多灵活性。
从实例上手
我们先从一个普通的mp4的播放形式上进行改造,由文件url的形式改为blob的方式,以加深对MSE的一点理解。
前端部分
代码不多,大概是这样子。注释中大概解释了基本的流程。
// MediaSource的readyState属性表示了其状态,分别有closed,open,ended三种
// closed:MS没有和媒体元素如video相关联。MS刚创建时就是该状态。
// open:source打开,并且准备接受通过sourceBuffer.APPendBuffer添加的数据。
// ended:当endOfStream()执行完成,会变为该状态。
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)
})
}
}
}
后端服务
后端服务主要是将一个视频文件以流的形式推给前端。
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)
})
遇到的坑是:一开始用的是自己本地随便找的一个视频文件,结果报错:
Uncaught DOMException: Failed to execute ‘endOfStream’ on ‘MediaSource’: The MediaSource’s readyState is not ‘open’.
原因是该MP4文件不是 framented mp4,不支持这种MSE的播放形式。最后在MDN上找了一个可用的MP4。
这里也提供一个转换的工具,支持将普通MP4转为 framented mp4
Bento4 MP4 & DASH Class Library, SDK and Tools
最后可以看到前端的video已经是用blob在播放了。
相关阅读
#include "stdafx.h"#include <iostream>#include <iomanip>#include "MediaInfoDLL.h" //Dynamicly-loaded library (.dll or .s
ResourceBundle与Properties读取配置文件
ResourceBundle与Properties的区别在于ResourceBundle通常是用于国际化的属性配置文件读取,Properties则是一般的属性配置文件读取
ResourceExhaustedError的原因及解决方式
在对see in the dark 代码进行测试时,我输入了一张[2848,4256,3]的ARW sony原始数据图片,运行后出现下面错误:tensorflow.python.f
spring boot datasource hikari 配置说明
hikari cp参数解释在:https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby原文如下:usernameThis property s
/mnt 是被系统管理员使用,手动挂载一些临时媒体设备的目录。/medai 是自动挂载的目录,比如我们的U盘插在ubuntu下回自动挂载,就会