注册

当老婆又让我下载一个腾讯视频时

我们结婚了!


是的,这次不是女朋友啦,是老婆了!


WechatIMG58.jpeg


时隔将近一个月,老婆又让我给她下载腾讯视频,如果按照上次探索的内容来下载的话,倒是可以一步步下载,合并,不过很麻烦,程序员不都是为了解决麻烦的吗,这么麻烦的步骤,有没有简单点呢。有!当然有,有很多简单的工具,上一期很多朋友给我推荐了各种工具,这里我没有一一查看,我可以列举出来,有需要的同学可以尝试看看,不想尝试的也可以看看我下面为了偷懒准备的方法。


心路历程


最初,我是想着把我之前的步骤,用无头浏览器加载一遍,然后用代码去下载ts片段,然后在机器上用ffmpeg进行合并,但是仿佛还是有些许麻烦,然后我就去npm搜了一下关键词:m3u8tomp4


image.png


m3u8-to-mp4


于是我点击了第一个包:m3u8-to-mp4


image.png


纳尼?这个包就一个版本,用了3年,而且周下载量还不少


image.png


于是我想着这个包要么就是很牛逼,一次性解决了m3u8转mp4的问题,一劳永逸,所以3年没更新过了,要么就是作者忘记了自己还有这个包


于是我就用了这个3年没人维护没人更新的包。


用法也很简单,就copy example 就好了。代码如下:



var m3u8ToMp4 = require("m3u8-to-mp4");
var converter = new m3u8ToMp4();
(async function() {
var url = "https://apd-666945ea97106754c57813479384d30c.v.smtcdns.com/omts.tc.qq.com/AofRtrergNwkAhpHs4RrxH2_9DWLWSG8xjDMZDQoFGyY/uwMROfz2r55kIaQXGdGnC2deOm68BrdPrRewQlOzrMAbixNO/svp_50001/cKAgRbCb6Re4BpHkI-IlK_KN1VJ8gQVK2sZtkHEY3vQUIlxVz7AtWmVJRifZrrPfozBS0va-SSJFhQhOFSKVNmqVi165fCQJoPl8V5QZBcGZBDpSIfrpCImJKryoZOdR5C0oGYkzIW77I4his7UkPY9Iwmf1QWjaHwNV2hpKv3aD9ysL_-YByA/szg_9276_50001_0bc3uuaa2aaafmaff4e3ijqvdjodbwsqadka.f304110.ts.m3u8?ver=4"
await converter
.setInputFile(url)
.setOutputFile("dummy.mp4")
.start();
console.log("File converted");
})();

视频地址是 v.qq.com/x/page/v331…


然后视频就转换成功了,哇哦!


so easy ! so beautiful!


原理


带着好奇,我想看下这个包是如何进行转换的


于是我点进去m3u8-to-mp4这个包文件


包文件内容如下


image.png


只有一个文件?


然后我打开了index.js ,只有64行😂


全部代码如下


/**
* @description M3U8 to MP4 Converter
* @author Furkan Inanc
* @version 1.0.0
*/

let ffmpeg = require("fluent-ffmpeg");

/**
* A class to convert M3U8 to MP4
* @class
*/
class m3u8ToMp4Converter {
/**
* Sets the input file
* @param {String} filename M3U8 file path. You can use remote URL
* @returns {Function}
*/
setInputFile(filename) {
if (!filename) throw new Error("You must specify the M3U8 file address");
this.M3U8_FILE = filename;

return this;
}

/**
* Sets the output file
* @param {String} filename Output file path. Has to be local :)
* @returns {Function}
*/
setOutputFile(filename) {
if (!filename) throw new Error("You must specify the file path and name");
this.OUTPUT_FILE = filename;

return this;
}

/**
* Starts the process
*/
start() {
return new Promise((resolve, reject) => {
if (!this.M3U8_FILE || !this.OUTPUT_FILE) {
reject(new Error("You must specify the input and the output files"));
return;
}

ffmpeg(this.M3U8_FILE)
.on("error", error => {
reject(new Error(error));
})
.on("end", () => {
resolve();
})
.outputOptions("-c copy")
.outputOptions("-bsf:a aac_adtstoasc")
.output(this.OUTPUT_FILE)
.run();
});
}
}

module.exports = m3u8ToMp4Converter;


大致看了下这个包做的内容,就是检测并设置了输入链接,和输出文件名,然后调用了fluent-ffmpeg这个库


???


站在巨人的肩膀上吗,自己就包了一层😂


接着看fluent-ffmpeg这个包,是如何实现转换的


image.png


然后我们在这个包文件夹下面搜索.run方法,用来定位到具体执行的地方


image.png


凭借多年的cv经验,感觉应该是processor.js这个文件里的,然后我们打开这个文件,定位到该方法处


image.png


往下看代码,我注意到了这段代码


image.png


因为都是基于ffmpeg这个大爹来做的工具,所以最底层也都是去调用ffmpeg的command


image.png


这几个if判断都是对结果进行捕获异常,那么我们在这个核心代码的地方打个端点看下


image.png


貌似是调用了几个命令行参数


于是我就有了一个大胆的想法!


image.png


是的,我手动在终端将这个命令拼接起来,用我的本地命令去跑应该也没问题的吧,于是我尝试了一下


image.png


没想到还成功了,其实成功是必然的,因为都是借助来ffmpeg这个包,只不过我是手动去操作,框架是代码去拼接这个命令而已


剩余的时间里,我看了看fluent-ffmpeg的其他代码,它做的东西比较多,比如去本查找ffmpeg的绝对路径啊,对ffmpeg的结果进行捕获异常信息等...



作者:小松同学哦
链接:https://juejin.cn/post/7033652317958176799

0 个评论

要回复文章请先登录注册