Use nodejs resolve m3u8 file format, and at ts merged into mp4
Before watching a video, the label directly to video, view a video address, then download it. .
It was discovered that a lot of tabs open video review of the elements, as follows:
Blob things started, can not download it. . .
In fact, we can still see the open network, load a bunch of .ts files. In fact, .ts file is to be cut into a section of the video. In theory, these files are downloaded, then the merger, completed ,,,
Word theory, thousands of lines of code ...
First, the problem
1, ts files in the end how much and addresses come from. . .
The answer: ts-related information, there is a file called m3u8 of. If the network is careful observation point can be found in the file of the request. The contents of the file is as follows:
This document, apparently, save the file name of each ts, of course, there exist a complete address. . Only need to extract the inside of the ts file name, plus the domain name of the destination site, you can download. .
I am here to m3u8 manually downloaded to the local, of course, you can write your own script file to download m3u8
Parsing code is as follows:
const fs = require("fs"); var source = fs.readFileSync("./test.m3u8","utf-8"); //读取 m3u8 var arr = source.split("\n"); arr = arr.filter((item)=>{ return item.match(/\.ts$/); });
2, what technology to combine these ts
Here I tried two approaches
The first: node js directly read using the file stream, into one file. . . The final result, the merger is indeed a success, but also to play, but Caton phenomenon, should be the video frame is destroyed.
The second: use a powerful tool, ffmpeg to merge, a success. Specific ffmpeg installation look here: https://www.cnblogs.com/xswl/p/10042195.html
Ffmpeg video synthesis instructions which I find to three categories:
ffmpeg -i "concat:1.ts|2.ts" -acodec copy out.mp3
ffmpeg -i "concat:1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
The first two categories, are to be spliced to the instructions inside the file name ,, considering the cmd command length is limited, so I did not used.
Enter the file using the following method:
ffmpeg -i input.txt -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
Input.txt which is an input configuration file, the contents of file names to be merged, as follows:
ffconcat version 1.0 file 0.ts file 1.ts
Second, the official start
New down.js writes:
Request the require = const ( "Request"); const the require FS = ( "FS"); const = the require path ( "path"); const = child_process the require ( 'child_process'); const = fsextra the require ( 'fsextra' ); module.exports = function (opt) { opt opt || = {}; var opt.arr || ARR = []; // file name, or address of all ts var host = opt.host || ""; // download ts domain, if arr which already contains the elements may not pass var outputName = opt.name || `output $ {(new Date ()) getTime ().} mp4`;. // exported video name const = tsFile path.join (__ dirname, `/ Source / $ {ARR [0] .split () [0]." "}`,.); createDir (tsFile); // Create a file recursively console.log ( "this interim resource files:", tsFile); const resultDir = path.join (__ dirname, "./ the Result"); createDir (resultDir); // create a file recursively resultFile path.join = const (resultDir, outputName); console.log ( "synthesized starting -----"); var localPath = []; // downloaded to the local path // begin downloading file ts Load (); function Load () { IF (arr.length> 0) { var arr.shift U = (); var = Host URL U +; console.log ( "Progress ---:", URL); Down (URL); } the else { // the download is complete console.log ( "the download is complete - start generating configuration"); localPath.unshift ( " Version 1.0 ffconcat "); the try { fs.writeFileSync (path.join (tsFile," ./ input.txt "), localPath.join (" \ n-"), undefined, 'UTF-. 8') } the catch (E) { the console.log ( "error writing configuration -", E); return; } // start the configuration-dependent synthesis child_process.exec ( `$ {CD} && tsFile FFmpeg -i input.txt -acodec Copy Copy -absf aac_adtstoasc -vcodec resultFile} {$`, function (error, stdout, stderr) { IF (error) { console.error ( "synthetic failure ---", error); } the else { console.log ( "synthesis of success -", stdout); // delete temporary files fsextra.remove (tsFile, ERR => { IF (ERR) return Console. error ( "delete file failed", ERR) the console.log ( 'file is removed successfully!') }); } }); } } // ts file download function Down (URL) { var P = url.split ( " ? ") [0]; var = path.parse nm (P); var = NME nm [" name "] + nm [" EXT "]; rpath = path.join(tsFile,nme); localPath.push ( `file $ {nme} `); // local cache path for synthesis Request ({ URL: URL, headers: { '- Agent-the User': 'the Mozilla / 5.0 (the Windows NT 6.1; the WOW64) AppleWebKit /537.36 (KHTML, like the Gecko) the Chrome / 71.0.3578.98 Safari / 537.36 ', ' X-Requested-With-':' the XMLHttpRequest ' } }, function (ERR, Response, body) { ! IF (ERR = && Response.StatusCode 200 is =) { Load (); } {the else the console.log ( "error", ERR) } }) pipe (fs.createWriteStream (rpath));. } // Create a folder recursive function mkdirs (dirpath is) { IF (! fs.existsSync (path.dirname (dirpath))) { mkdirs (path.dirname(dirpath)); } FS.mkdirSync(dirpath); } function createDir(myPath){ fs.existsSync(myPath) == false && mkdirs(myPath); } } //ffmpeg -i "concat:1.ts|2.ts" -acodec copy out.mp3 //ffmpeg -i "concat:1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4 // ffmpeg -i input.txt -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4 /* ffconcat version 1.0 file 0.ts file 1.ts */ /* //文件移动 function moveFile(oldPath,newPath){ try { fs.renameSync(oldPath, newPath); } catch (e) { console.log("报错后强制移动",e); fs.renameSync(oldPath, newPath); } } */
And then create main.js
const fs = require("fs"); const down = require("./down"); var host = 'https://xxxx/';目标网站 var outputName = "output.mp4"; var source = fs.readFileSync("./test.m3u8","utf-8"); //读取 m3u8 var arr = source.split("\n"); arr = arr.filter((item)=>{ return item.match(/\.ts$/); }); down({ arr, host, outputName })
Which used to fs-extra module, the install
above sea level and extra-fs
The last execution:
node main.js