
在最近的项目中,您需要在前端播放.ts格式的视频. 经过几天的学习,您已经学到了很多知识. 您还发现了一个前所未有的出色解决方案,并与具有相同需求的学生共享.
在Internet上找到的大多数解决方案都使用诸如videojs之类的网络播放器来接收.m3u8索引文件来播放ts切片. 该解决方案的缺点是后端需要处理原始的ts切片以生成.m3u8索引文件

ffmpeg -i source.ts -c copy -map 0 -f segment -segment_list playlist.m3u8 -segment_time 10 outputd.ts
项目中存储了大量.ts片,它们占用了NAS服务器的大部分资源. 尽管.m3u8索引文件非常小,但它还会生成一堆新的切片.ts视频,例如上面的说明将生成一堆ts新的,长度为10s的切片. 出于各种考虑,后端同学拒绝了这种重新生成新切片和索引的方案.

在我们的项目中,每个ts切片已经是具有独立内容的视频,并且持续时间在20秒以内,因此实际上不需要剪切,只需要生成索引文件即可. .m3u8格式如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:93
#EXTINF:92.008578,
test.ts
#EXT-X-ENDLIST

定义的持续时间不影响最终Web播放器计算的持续时间,因此可以采用统一的最大值. 总体而言,仅需根据不同的ts视频修改ts文件名的倒数第二行,即可使用该脚本. 该脚本统一为所有ts文件生成索引文件. 这个计划非常低ts文件用什么播放,当然被后端同学拒绝了.
VLC Web插件,该解决方案需要VLC播放器和浏览器插件,并且不支持Chrome. 使用起来很复杂. 有兴趣的学生可以自己尝试.

中文互联网搜索失败后,我果断地求助于Google,但也失败了. 就在我拼命准备调整心态并接受下载后VLC播放的自底向上解决方案时ts文件用什么播放,我终于找到了一个线索. 在vediojs的Github页面上,在Issue1441和Issue4297中,面对videojs是否可以直接播放.ts的问题,开发团队表示,尽管库本身没有直接相关的实现,但可以使用相关的逻辑来实现. 最重要的是要指出工具mux.js. 根据实际测量,仅此库可用于直接在网络上播放.ts视频. 以下是其转换过程.

在示例中,.ts二进制数据以ajax模式接收. mux.js的介绍方法可以通过标签直接导入,也可以在npm安装mux.js之后导入到页面中.
var $ = document.querySelector.bind(document);
var vjsParsed,
video,
mediaSource;
// 定义通用的事件回调处理函数,只做打印事件类型
function logevent (event) {
console.log(event);
}
// ajax
let xhr = new XMLHttpRequest();
xhr.open(GET, ./test.ts);
// 接收的是 video/mp2t 二进制数据,并且arraybuffer类型方便后续直接处理
xhr.responseType = arraybuffer;
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState ==4) {
if (xhr.status == 200) {
transferFormat(xhr.response);
} else {
console.log(error);
}
}
}
function transferFormat (data) {
// 将源数据从ArrayBuffer格式保存为可操作的Uint8Array格式
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
var segment = new Uint8Array(data);
var combined = false;
// 接收无音频ts文件,OutputType设置为video,带音频ts设置为combined
var outputType = video;
var remuxedSegments = [];
var remuxedBytesLength = 0;
var remuxedInitSegment = null;
// remux选项默认为true,将源数据的音频视频混合为mp4,设为false则不混合
var transmuxer = new muxjs.mp4.Transmuxer({remux: false});
// data事件,开始转换流
transmuxer.on(data, function(event) {
console.log(event);
if (event.type === outputType) {
remuxedSegments.push(event);
remuxedBytesLength += event.data.byteLength;
remuxedInitSegment = event.initSegment;
}
});
// 转换完成事件,拼接最后结果并传入MediaSource
transmuxer.on(done, function () {
var offset = 0;
var bytes = new Uint8Array(remuxedInitSegment.byteLength + remuxedBytesLength)
bytes.set(remuxedInitSegment, offset);
offset += remuxedInitSegment.byteLength;
for (var j = 0, i = offset; j < remuxedSegments.length; j++) {
bytes.set(remuxedSegments[j].data, i);
i += remuxedSegments[j].byteLength;
}
remuxedSegments = [];
remuxedBytesLength = 0;
// 解析出转换后的mp4相关信息,与最终转换结果无关
vjsParsed = muxjs.mp4.tools.inspect(bytes);
console.log(transmuxed, vjsParsed);
prepareSourceBuffer(combined, outputType, bytes);
});
// push方法可能会触发data事件,因此要在事件注册完成后调用
transmuxer.push(segment); // 传入源二进制数据,分割为m2ts包,依次调用上图中的流程
// flush的调用会直接触发done事件,因此要事件注册完成后调用
transmuxer.flush(); // 将所有数据从缓存区清出来
}
function prepareSourceBuffer (combined, outputType, bytes) {
var buffer;
video = document.createElement(video);
video.controls = true;
// MediaSource Web API: https://developer.mozilla.org/zh-CN/docs/Web/API/MediaSource
mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
$(#video-wrapper).appendChild(video); // 将H5 video元素添加到对应DOM节点下
// 转换后mp4的音频格式 视频格式
var codecsArray = [avc1.64001f, mp4a.40.5];
mediaSource.addEventListener(sourceopen, function () {
// MediaSource 实例默认的duration属性为NaN
mediaSource.duration = 0;
// 转换为带音频、视频的mp4
if (combined) {
buffer = mediaSource.addSourceBuffer(video/mp4;codecs= + avc1.64001f,mp4a.40.5 + );
} else if (outputType === video) {
// 转换为只含视频的mp4
buffer = mediaSource.addSourceBuffer(video/mp4;codecs= + codecsArray[0] + );
} else if (outputType === audio) {
// 转换为只含音频的mp4
buffer = mediaSource.addSourceBuffer(audio/mp4;codecs= + (codecsArray[1] ||codecsArray[0]) + );
}
buffer.addEventListener(updatestart, logevent);
buffer.addEventListener(updateend, logevent);
buffer.addEventListener(error, logevent);
video.addEventListener(error, logevent);
// mp4 buffer 准备完毕,传入转换后的数据
// 将 bytes 放入 MediaSource 创建的sourceBuffer中
// https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/appendBuffer
buffer.appendBuffer(bytes);
// 自动播放
// video.play();
});
};
IE8及更高版本,IE Edge,Chrome,Firefox可以正常播放. 我希望本文可以帮助您培养学生.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-187966-1.html
军演准备