Toggle navigation
leo's blog
PHP
JavaScript
MySQL
Linux
瞎扯
ckplayer播放m3u8格式无法播放问题的
JavaScript
2021-05-20 23:15:24
0
简介:
最近在开发一个音频播放的功能,由于音频格式是m3u8格式,所以选择使用了ckplayer播放器来实现。按照官方文档的说明很简单的就实现了播放功能。后面测试发现部分音频文件无法播放。各种检查后发现是ts文件载入的原因。ckplayer播放m3u8格式的音视频文件时是通过使用hlsjs直接载入文件中所记录的ts文件。所以有可能会导致载入的文件错误。最终导致音视频文件无法播放。
最近在开发一个音频播放的功能,由于音频格式是m3u8格式,所以选择使用了ckplayer播放器来实现。按照官方文档的说明很简单的就实现了播放功能:laughing: 后面测试发现部分音频文件无法播放。各种检查后发现是ts文件载入的原因。所以记录下解决的过程 ### 1、当前的调用代码 ```html <div class="video" style="height: 982px;" id="video"></div> <script type="text/javascript" src="/static/plugs/ckplayer/ckplayer.js" charset="utf-8" data-name="ckplayer"></script> <script type="text/javascript"> //定义一个变量:videoObject,用来做为视频初始化配置 var videoObject = { container: '.video', //“#”代表容器的ID,“.”或“”代表容器的class variable: 'player', //播放函数名称,该属性必需设置,值等于下面的new ckplayer()的对象 video: "{:get_channel_video($info['recording_url'])}", autoplay:true, poster: '__ROOT__/static/plugs/ckplayer/material/poster.jpg', //封面图片 html5m3u8:true }; var player = new ckplayer(videoObject);//初始化播放器 </script> ``` ###2、检查m3u8文件的地址 可以手动的先访问下文件地址是否可以访问。如果无法访问可以肯定是地址错误。 ### 3、检查跨域问题 按照官方文档的说明 需要在请求的服务器上增加安全策略文件crossdomain.xml。只要确保请求的文件地址对应的服务器容许跨域即可 ###4、抓包检查可以播放的音频文件 1、查看m3u8文件的请求信息  2、检查ts文件的请求信息 由于m3u8是使用文本方式对媒体文件进行描述。所以后续会根据文件中记录的传输流文件的地址信息继续加载记录的ts文件  ### 5、抓包检查不能播放的音频文件 1、查看m3u8的请求信息  2、检查ts文件的请求信息  ### 6、解决问题思路 1、通过查看请求的信息发现不能播放的音频文件的ts文件无法载入。所以肯定音频文件无法播放了。 2、在请求ts的时候发现请求的地址不对劲。是直接请求的本项目下的文件,但是这些音频文件都是存储在了cdn服务器上啊 怎么可能错误呢 3、通过追踪ckplayer的js文件,发现m3u8的文件是通过使用hlsjs进行载入然后解析的。但是hls载入ts文件的时候是直接使用m3u8文件中的地址进行载入并没有根据m3u8的文件进行计算直接载入 4、此时由于很多音频文件已经生成了也不想修改服务端在生成m3u8文件的格式。所以需要修改下hls的载入文件的方式 。根据m3u8文件的内容中的地址综合进行载入 ### 7、解决问题 1、查找代码loadInternal ```javascript value: function loadInternal() ``` 大约在15275行左右 2、修改方法的内容 ```javascript value: function loadInternal() { var xhr, context = this.context; if (typeof XDomainRequest !== 'undefined') { xhr = this.loader = new XDomainRequest(); } else { xhr = this.loader = new XMLHttpRequest(); } var stats = this.stats; stats.tfirst = 0; stats.loaded = 0; var xhrSetup = this.xhrSetup; //增加了地址的判断 如果是https协议的请求直接加载否则使用m3u8的基础地址进行加载 //context对象下frag下的baseurl记录了m3u8文件的地址 可以自己打印出来查看详细信息 let url = context.url; if (url.substr(0, 8) != "https://") { url = context.frag.baseurl.substring(0, context.frag.baseurl.lastIndexOf("/") + 1) + url; } if (xhrSetup) { try { xhrSetup(xhr, url); } catch(e) { // fix xhrSetup: (xhr, url) => {xhr.setRequestHeader("Content-Language", "test");} // not working, as xhr.setRequestHeader expects xhr.readyState === OPEN xhr.open('GET', url, true); xhrSetup(xhr, url); } } if (!xhr.readyState) { // xhr.open('GET', context.url, true); xhr.open('GET', url, true); } if (context.rangeEnd) { xhr.setRequestHeader('Range', 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1)); } xhr.onreadystatechange = this.readystatechange.bind(this); xhr.onprogress = this.loadprogress.bind(this); xhr.responseType = context.responseType; // setup timeout before we perform request this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), this.config.timeout); xhr.send(); } ```
Top