Web端直接播放 .ts 视频及mux.js播放ts视频没有声音

news/2024/10/18 8:20:33/

最近项目中需要前端播放 .ts 格式视频,捣鼓了几天学习到很多知识,也发掘了一种优秀的解决方案,分享给有同样需求的同学。

常见方案

在网上查找的大部分解决方案都是用诸如videojs等网页播放器,接收 .m3u8索引文件的方式来播放ts切片。这种方案的缺点是需要后端对原始ts切片做处理,生成 .m3u8索引文件

ffmpeg -i source.ts -c copy -map 0 -f segment -segment_list playlist.m3u8 -segment_time 10 output%03d.ts

项目中已存储的 .ts 切片数量众多,已经占用了NAS服务器绝大部分的资源,生成的 .m3u8 索引虽然非常小,但会生成一堆切片后的新 .ts 视频,例如上述指令将会生成一堆 10s 长度的 ts新切片。出于各种考虑后端的同学拒绝了这种重新生成新切片加索引的方案。

邪道方案

在我们的项目中,每一个ts切片已经就是一个独立内容的视频了,时长在20s以内,因此其实不用切割,只需要生成一个索引文件就可以了, .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

定义好的时长并不影响最终网页播放器计算出的时长,因此可以取一个统一的极大值,整体上就只有倒数第二行的ts文件名需要根据不同 ts 视频修改,可以用脚本统一生成所有ts文件的索引文件。这个方案极其low,当然也被后端同学拒绝了。

插件方案

VLC Web Plugin,一个需要VLC播放器以及浏览器插件的方案,并且不支持Chrome,使用复杂,感兴趣的同学可以自行尝试。

优雅方案

在中文互联网搜索无果后,果断转向了Google,然而也未果,正当我绝望地准备调整心态,接受下载后VLC播放的保底方案时,终于发现了一丝线索,在vediojs的Github页面中,Issue1441 和 Issue4297中,面对videojs能否直接播放 .ts 的疑问,开发团队都表示虽然库本身没有直接的相关实现,但可以利用相关的逻辑自行实现。最重要的是都指出了mux.js这一工具。根据实测,只用这一个库即可在web端直接播放 .ts 视频,如下是它的转化流程。

代码示例

示例中是以 ajax 的方式接收 .ts 二进制数据,mux.js引入方式可以直接标签引入,也可以npm install mux.js后 import进页面。

var $ = document.querySelector.bind(document);var vjsParsed,video, mediaSource;// 定义通用的事件回调处理函数,只做打印事件类型function logevent (event) {console.log(event);}// ajaxlet xhr = new XMLHttpRequest();xhr.open('GET', "./test.ts");// 接收的是 video/mp2t 二进制数据,Blob类型也可以,但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/ArrayBuffervar 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;}});// 监听转换完成事件,拼接最后结果并传入MediaSourcetransmuxer.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/MediaSourcemediaSource = 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属性为NaNmediaSource.duration = 0;// 转换为带音频、视频的mp4if (combined) {buffer = mediaSource.addSourceBuffer('video/mp4;codecs="' + 'avc1.64001f,mp4a.40.5' + '"');} else if (outputType === 'video') {// 转换为只含视频的mp4buffer = mediaSource.addSourceBuffer('video/mp4;codecs="' + codecsArray[0] + '"');} else if (outputType === 'audio') {// 转换为只含音频的mp4buffer = 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/appendBufferbuffer.appendBuffer(bytes);// 自动播放// video.play();});};

IE8及以上 、 IE Edge 、Chrome 、 Firefox 浏览器下均能正常播放。希望本文能帮到各位开发同学。

前端mux.js播放ts视频没有声音

代码:

`var $ = document.querySelector.bind(document);

var vjsParsed,video, mediaSource;
// 定义通用的事件回调处理函数,只做打印事件类型
function logevent (event) {console.log(event);
}// ajax
let xhr = new XMLHttpRequest();
xhr.open('GET', "./AM_1.044.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/ArrayBuffervar segment = new Uint8Array(data); var combined = false;// 接收无音频ts文件,OutputType设置为'video',带音频ts设置为'combined'var outputType = 'combined';var remuxedSegments = [];var remuxedBytesLength = 0;var remuxedInitSegment = null;// remux选项默认为true,将源数据的音频视频混合为mp4,设为false则不混合var transmuxer = new muxjs.mp4.Transmuxer({remux: true});// 监听data事件,开始转换流transmuxer.on('data', function(event) {console.log(event);if (event.type === outputType) {remuxedSegments.push(event);remuxedBytesLength += event.data.byteLength;remuxedInitSegment = event.initSegment;}});// 监听转换完成事件,拼接最后结果并传入MediaSourcetransmuxer.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/MediaSourcemediaSource = new MediaSource(); video.src = URL.createObjectURL(mediaSource);$('#video-place').appendChild(video);// 转换后mp4的音频格式 视频格式var codecsArray = ["avc1.64001f", "mp4a.40.5"];mediaSource.addEventListener('sourceopen', function () {// MediaSource 实例默认的duration属性为NaNmediaSource.duration = 0;// 转换为带音频、视频的mp4if (combined) {buffer = mediaSource.addSourceBuffer('video/mp4;codecs="' + 'avc1.64001f,mp4a.40.5' + '"');} else if (outputType === 'video') {// 转换为只含视频的mp4buffer = mediaSource.addSourceBuffer('video/mp4;codecs="' + codecsArray[0] + '"');} else if (outputType === 'audio') {// 转换为只含音频的mp4buffer = 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 准备完毕,传入转换后的数据// return callback(buffer);// 将 bytes 放入 MediaSource 创建的sourceBuffer中// https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/appendBufferbuffer.appendBuffer(bytes);// 自动播放// video.play();});
};`

没有办法打开喇叭,按照网上提供的教程依然是这样。转码出来的视频没得声音,可以确认的是原视频有声音,
如图:


源代码地址:https://github.com/SunnySunMo...

解决办法:

章鱼丸子?:

解决了吗?怎么解决的啊?我现在也遇到一样的问题了

回复2 月 10 日

自由的心:

var combined = false;
// 接收无音频ts文件,OutputType设置为'video',带音频ts设置为'combined'

修改为: var combined = !0;//false;

转载于:https://segmentfault.com/a/1190000018503818

              https://segmentfault.com/q/1010000038782380

 


http://www.ppmy.cn/news/629609.html

相关文章

Linux进程间通信——管道(下)

前文 一&#xff0c;什么是命名管道? 二&#xff0c;命名管道的基本原理 三&#xff0c;创建命名管道实现两个进程对写 四&#xff0c;匿名管道和命名管道的区别 总结 前文 上篇文章我们主要讲了匿名管道的定义以及基本原理&#xff0c;但是匿名管道有一个致命的缺陷&#…

【数据结构】单链表(超全)

目录 一、什么是链表&#xff1f;1.1 定义1.2 链表的分类 二、无头单向非循环链表2.1 结构2.2 如何遍历链表数据2.3 尾插2.4 创建新节点2.5 头插2.6 尾删2.7 头删2.8 单链表查找2.9 在pos位置之前插入2.10 删除pos位置数据2.11 在pos位置的后面插入2.12 删除pos位置后面的数据 …

PS一键磨皮美白扩展插件Delicious Retouch 5.0 汉化集合版 Win/Mac

PhotoShop DR磨皮插件是一款PS上的专业美颜插件&#xff0c;用了之后你会感叹原来修图也会如此简单&#xff0c;插件适用于CC2019后期调色美妆&#xff0c;无需专业技巧&#xff0c;轻轻一涂&#xff0c;胜过十年修为&#xff01; 2019全网最新的人像美容扩展面板插件——DR5最…

ps插件套装imagenomic磨皮滤镜安装教程

为大家推荐一款知名的PS磨皮降噪滤镜套装,Imagenomic Professional Suite mac版中包含noiseware降噪插件、portraiture3磨皮滤镜和Realgrain胶片效果滤镜插件,各有各的功能,轻松进行磨皮、添加胶片效果、降噪等操作,小编这里准备了最新的imagenomic滤镜破解教程,赶紧试试i…

Portraiture4安装许可证密钥免费下载

作为 PS 的插件&#xff0c;被众多照片后期高手使用&#xff0c;评价颇高。主要原因在于它操作简便、磨皮效果好、软件很小&#xff0c;特别是它可以自动感应皮肤区域磨皮&#xff0c;只对皮肤作用更令人称奇的是&#xff1a;Portraiture 磨皮能保留下细小的毛孔和皮肤质感&…

全新升级版Portraiture 4.1磨皮插件安装许可证密钥免费版含使用教程

2023年全新发布Portraiture 4. 1是专注于图像后期处理软件研发的 Imagenomic, LLC产品之一&#xff0c;在摄影爱好者中有点影响力。Portraiture可以将繁琐复杂的人像磨皮操作极致简化&#xff0c;不论是普通爱好者或专业后期处理人员&#xff0c;均能一键完成。凭借优秀的AI算法…

ps磨皮滤镜插件Portraiture for Mac 破解方法

Portraiture for Mac 破解版是Photoshop上自动皮肤平滑、愈合和增强效果的插件&#xff0c;这款Portraiture 3 ps磨皮滤镜插件主要对人像进行皮肤修饰、磨皮润色处理&#xff0c;Portraiture3滤镜可以平滑和去除缺陷&#xff0c;同时保留皮肤纹理和重要的人像细节&#xff0c;小…

给PhotoShop安装Portraiture插件

目录 1. 插件下载地址2. 装入PhotoShop3. 注册使用4. 使用界面 1. 插件下载地址 Portraiture插件下载地址 里面有四个文件&#xff0c;第四个是注册机&#xff1b; 2. 装入PhotoShop 打开PhotoShop文件夹中Plug-ins文件夹&#xff1b; 将插件复制到文件夹里面&#xff1b; …