1 分析
在网上查了一下这类视频的下载方法,关键是找到相应的.m3u8文件(通常是index.m3u8):
在这个.m3u8文件中包括这个视频对应的所有.ts文件列表。
把这些.ts文件下载回来,再用ffmpeg这个工具把这些.ts文件合并起来。
2 思路
网上有用Python来实现的方法和代码。
不过由于.m3u8文件中通常也包括了插入的广告的.ts文件,所以还要进一步区分处理。
思路1是用javascript直接生成需要下载的.ts文件列表
思路2是用javascript从.m3u8文件提取.ts文件列表,然后进行区分
接着用专业下载软件来下载.ts文件。
再用ffmpeg这个工具把这些.ts文件合并起来。
这里我们先用思路1来实现。
3 实现
3.1 编写界面
用html来实现。
视频.ts文件url通常是
http://www.abc.com/video/def0000.ts
http://www.abc.com/video/def0001.ts
http://www.abc.com/video/def0002.ts
……
http://www.abc.com/video/def1000.ts
所以我们的界面包括以下组件:
1.Url文本框:存放要下载的ts文件的url通用部分,比如http://www.abc.com/video/。
2.文件名前缀文本框:ts文件名中固定的文字,比如def。
3.起 始 数 字文本框:ts.文件名数字部分的起始值,通常是第1个.ts文件中数字部分,比如0000。
4.结 束 数 字文本框:ts.文件名数字部分的结束值,通常是最后1个.ts文件中数字部分,比如1000。
5.文件列表:保存生成的.ts文件url列表
6.生成文件列表按钮。点击后根据组件1-4的值来生成.ts文件url列表,保存到5。
<!DOCTYPE html> <html> <head> <meta name="Author" content="PurpleEndurer"> <title>生成ts文件Url列表</title> </head> <body> <body> <fieldset> <!-- 表单字段集 --> <legend> 生成文件列表 </legend> <table> <tr> <td> <p>参数设置:</p> <p> Url:<input type="text" id="txtUrl" > <p>文件名前缀:<input type="text" id="txtFnPre" > <p>起 始 数 字:<input type="text" id="txtFnStartN" value="0"></p> <p>结 束 数 字:<input type="text" id="txtFnEndN" value="1000"></P> <p> </td> <td> <p>文件列表:</p> <textarea name="" rows="12" cols="80" id="taFileList"></textarea> </td> </tr> </table> <p> <input type="button" value="生成文件列表" onclick="genFileList()"> </p> </fieldset> <div id="divDbg" style="width:100%; height: 400px; border:green 1px solid; color:green; overflow:auto;">调试信息:</div> </body> </html>
3.2 生成文件列表的代码
3.2.1 数值验证
起始数字、结束数字 都是数字,我们可以用正则表达式来验证。
//判断是否为自然数(非负整数) //n:numbder function isNaturalNumber(n) { var reg=/^[0-9]+?$/; return reg.test(n); }// isNaturalNumber(n)
3.2.2 字符填充
比如第1个ts文件名是0000.ts,我们的起始数字是0,那么要生成为0000才行。
要实现这个功能,我们可以自己编程实现,网上也可以找到相应的实现代码。
现在我们也可以使用字符串对象的padStart方法来实现。
padStart方法的语法是:
str.padStart(targetLength [, padString])
padStart()方法的功能是用另一个字符串填充当前字符串(重复,如果需要的话),以便产生的字符串达到给定的长度。填充从当前字符串的开始(左侧)应用的。
其中的长度我们可以根据要下载的最后一个ts文件来确定。
例如:
document.write('0'.padStart(4, "0")); // 输出:0000 document.write('0'.padStart(4, 0)); //输出:0000
3.2.3 for循环
我们将用for循环来生成ts文件url列表。
由于起始数字和结束数字都是从文本框获取的,默认是字符串类型。
所以我们在用起始数字和结束数字实现for循环时,要注意类型转换。可以用Number()来实现字符串类型到数字类型的转换。
4.完整代码
<!DOCTYPE html> <html> <head> <meta name="Author" content="PurpleEndurer"> <title>>生成ts文件Url列表</title> </head> <body> <body> <fieldset> <!-- 表单字段集 --> <legend> 生成文件列表 </legend> <table> <tr> <td> <p>参数设置:</p> <p> Url:<input type="text" id="txtUrl" > <p>文件名前缀:<input type="text" id="txtFnPre" > <p>起 始 数 字:<input type="text" id="txtFnStartN" value="0"></p> <p>结 束 数 字:<input type="text" id="txtFnEndN" value="1000"></P> <p> </td> <td> <p>文件列表:</p> <textarea name="" rows="12" cols="80" id="taFileList"></textarea> </td> </tr> </table> <p> <input type="button" value="生成文件列表" onclick="genFileList()"> <input type="button" value="提取文件列表" onclick="getFileList()"> </p> </fieldset> <div id="divDbg" style="width:100%; height: 400px; border:green 1px solid; color:green; overflow:auto;">调试信息:</div> <script> var txtUrl = document.getElementById("txtUrl"); var txtFnPre = document.getElementById("txtFnPre"); var txtFnStartN = document.getElementById("txtFnStartN"); var txtFnEndN = document.getElementById("txtFnEndN"); var taFileList = document.getElementById("taFileList"); var divDbg = document.getElementById("divDbg"); //判断是否为自然数(非负整数) //n:numbder function isNaturalNumber(n) { var reg=/^[0-9]+?$/; return reg.test(n); }// isNaturalNumber(n) //判断是否为正整数 //n:numbder function isPositiveInteger(n) { var reg=/^[1-9]\d*$/; return reg.test(n); }// isNaturalNumber(n) function genFileList() { var sUrl = txtUrl.value; var sF1 = txtFnPre.value; var sF2 = txtFnStartN.value; var sF3 = txtFnEndN.value; if (! isNaturalNumber(sF2)) { alert('起始数字不是数字'); return } var iF2 = Number(sF2); var sF3 = txtFnEndN.value; if (! isNaturalNumber(sF3)) { alert('结束数字不是数字'); return; } var iF3 = Number(sF3); if (iF3 < iF2) { alert('结束数字 小于 起始数字'); return; } divDbg.innerHTML += "sUrl=" + (sUrl.length > 0 ? sUrl : '空') + " sF1= " + (sF1.length > 0 ? sF1 : '空') + " sF2=" + (sF2.length > 0 ? sF2 : '空') + typeof(sF2) + " sF3=" + sF3 + typeof(sF2) + "<br> verify ok." var f = '', f1=''; var iFileNameLen = sF3.length; //alert(iFileNameLen); //for (var i = Number(sF2); i < Number(sF3); i++) for (var i = iF2; i < iF3; i++) { taFileList.value += sUrl + sF1 + i.toString().padStart(iFileNameLen, 0)+ '.ts\n'; divDbg.innerHTML += "<br> i=" + i + typeof(i++) + ": " ; } } // genFileList() </script> </body> </html>