Skip to content

Commit

Permalink
improve segment/key url match
Browse files Browse the repository at this point in the history
  • Loading branch information
ying_123 committed Jan 23, 2024
1 parent ba03141 commit 6125462
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 50 deletions.
9 changes: 4 additions & 5 deletions dist/hls2mp4.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1058,17 +1058,16 @@ var Hls2Mp4 = /** @class */ (function () {
Hls2Mp4.prototype.downloadM3u8 = function (url) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var m3u8Parsed, _d, content, parsedUrl, keyMatchRegExp, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var m3u8Parsed, _d, content, parsedUrl, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var e_1, _e;
return __generator(this, function (_f) {
switch (_f.label) {
case 0: return [4 /*yield*/, this.parseM3u8(url)];
case 1:
m3u8Parsed = _f.sent();
_d = m3u8Parsed, content = _d.content, parsedUrl = _d.url;
keyMatchRegExp = createFileUrlRegExp('key', 'gi');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="' + keyMatchRegExp.source + '"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|' + createFileUrlRegExp('ts', 'gi').source, 'g');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="[^"]+"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|(?<=#EXTINF:\\d+(\\.\\d+)?,\\n).+', 'gim');
matches = content.match(matchReg);
if (!matches) {
throw new Error('Invalid m3u8 file, no ts file found');
Expand All @@ -1077,7 +1076,7 @@ var Hls2Mp4 = /** @class */ (function () {
for (i = 0; i < matches.length; i++) {
matched = matches[i];
if (matched.match(/#EXT-X-KEY/)) {
matchedKey = (_a = matched.match(keyMatchRegExp)) === null || _a === void 0 ? void 0 : _a[0];
matchedKey = (_a = matched.match(/(?<=URI=").+(?=")/)) === null || _a === void 0 ? void 0 : _a[0];
matchedIV = (_c = (_b = matched.match(/IV=\w+$/)) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.replace(/^IV=/, '');
segments.push({
key: matchedKey,
Expand Down
9 changes: 4 additions & 5 deletions dist/hls2mp4.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,17 +1054,16 @@ var Hls2Mp4 = (function (exports, ffmpeg, util) {
Hls2Mp4.prototype.downloadM3u8 = function (url) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var m3u8Parsed, _d, content, parsedUrl, keyMatchRegExp, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var m3u8Parsed, _d, content, parsedUrl, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var e_1, _e;
return __generator(this, function (_f) {
switch (_f.label) {
case 0: return [4 /*yield*/, this.parseM3u8(url)];
case 1:
m3u8Parsed = _f.sent();
_d = m3u8Parsed, content = _d.content, parsedUrl = _d.url;
keyMatchRegExp = createFileUrlRegExp('key', 'gi');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="' + keyMatchRegExp.source + '"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|' + createFileUrlRegExp('ts', 'gi').source, 'g');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="[^"]+"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|(?<=#EXTINF:\\d+(\\.\\d+)?,\\n).+', 'gim');
matches = content.match(matchReg);
if (!matches) {
throw new Error('Invalid m3u8 file, no ts file found');
Expand All @@ -1073,7 +1072,7 @@ var Hls2Mp4 = (function (exports, ffmpeg, util) {
for (i = 0; i < matches.length; i++) {
matched = matches[i];
if (matched.match(/#EXT-X-KEY/)) {
matchedKey = (_a = matched.match(keyMatchRegExp)) === null || _a === void 0 ? void 0 : _a[0];
matchedKey = (_a = matched.match(/(?<=URI=").+(?=")/)) === null || _a === void 0 ? void 0 : _a[0];
matchedIV = (_c = (_b = matched.match(/IV=\w+$/)) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.replace(/^IV=/, '');
segments.push({
key: matchedKey,
Expand Down
9 changes: 4 additions & 5 deletions dist/hls2mp4.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -1057,17 +1057,16 @@
Hls2Mp4.prototype.downloadM3u8 = function (url) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var m3u8Parsed, _d, content, parsedUrl, keyMatchRegExp, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var m3u8Parsed, _d, content, parsedUrl, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var e_1, _e;
return __generator(this, function (_f) {
switch (_f.label) {
case 0: return [4 /*yield*/, this.parseM3u8(url)];
case 1:
m3u8Parsed = _f.sent();
_d = m3u8Parsed, content = _d.content, parsedUrl = _d.url;
keyMatchRegExp = createFileUrlRegExp('key', 'gi');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="' + keyMatchRegExp.source + '"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|' + createFileUrlRegExp('ts', 'gi').source, 'g');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="[^"]+"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|(?<=#EXTINF:\\d+(\\.\\d+)?,\\n).+', 'gim');
matches = content.match(matchReg);
if (!matches) {
throw new Error('Invalid m3u8 file, no ts file found');
Expand All @@ -1076,7 +1075,7 @@
for (i = 0; i < matches.length; i++) {
matched = matches[i];
if (matched.match(/#EXT-X-KEY/)) {
matchedKey = (_a = matched.match(keyMatchRegExp)) === null || _a === void 0 ? void 0 : _a[0];
matchedKey = (_a = matched.match(/(?<=URI=").+(?=")/)) === null || _a === void 0 ? void 0 : _a[0];
matchedIV = (_c = (_b = matched.match(/IV=\w+$/)) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.replace(/^IV=/, '');
segments.push({
key: matchedKey,
Expand Down
9 changes: 4 additions & 5 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,17 +1054,16 @@ var Hls2Mp4 = /** @class */ (function () {
Hls2Mp4.prototype.downloadM3u8 = function (url) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var m3u8Parsed, _d, content, parsedUrl, keyMatchRegExp, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var m3u8Parsed, _d, content, parsedUrl, keyTagMatchRegExp, matchReg, matches, segments, i, matched, matchedKey, matchedIV, batch, treatedSegments, segments_1, segments_1_1, group, total, keyBuffer, keyUrl, _loop_1, this_1, i, e_1_1, m3u8;
var e_1, _e;
return __generator(this, function (_f) {
switch (_f.label) {
case 0: return [4 /*yield*/, this.parseM3u8(url)];
case 1:
m3u8Parsed = _f.sent();
_d = m3u8Parsed, content = _d.content, parsedUrl = _d.url;
keyMatchRegExp = createFileUrlRegExp('key', 'gi');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="' + keyMatchRegExp.source + '"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|' + createFileUrlRegExp('ts', 'gi').source, 'g');
keyTagMatchRegExp = new RegExp('#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="[^"]+"(,IV=\\w+)?)?', 'gi');
matchReg = new RegExp(keyTagMatchRegExp.source + '|(?<=#EXTINF:\\d+(\\.\\d+)?,\\n).+', 'gim');
matches = content.match(matchReg);
if (!matches) {
throw new Error('Invalid m3u8 file, no ts file found');
Expand All @@ -1073,7 +1072,7 @@ var Hls2Mp4 = /** @class */ (function () {
for (i = 0; i < matches.length; i++) {
matched = matches[i];
if (matched.match(/#EXT-X-KEY/)) {
matchedKey = (_a = matched.match(keyMatchRegExp)) === null || _a === void 0 ? void 0 : _a[0];
matchedKey = (_a = matched.match(/(?<=URI=").+(?=")/)) === null || _a === void 0 ? void 0 : _a[0];
matchedIV = (_c = (_b = matched.match(/IV=\w+$/)) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.replace(/^IV=/, '');
segments.push({
key: matchedKey,
Expand Down
4 changes: 2 additions & 2 deletions dist/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hls2mp4",
"version": "1.2.5",
"version": "1.2.6",
"description": "a tool for download hls/m3u8 to mp4",
"main": "index.js",
"types": "index.d.ts",
Expand Down Expand Up @@ -43,4 +43,4 @@
"last 1 safari version"
]
}
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hls2mp4",
"version": "1.2.5",
"version": "1.2.6",
"description": "a tool for download hls/m3u8 to mp4",
"main": "index.js",
"types": "index.d.ts",
Expand Down
58 changes: 31 additions & 27 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,13 @@ class Hls2Mp4 {
private async downloadM3u8(url: string) {
const m3u8Parsed = await this.parseM3u8(url)
let { content, url: parsedUrl } = m3u8Parsed!;
const keyMatchRegExp = createFileUrlRegExp('key', 'gi');
const keyTagMatchRegExp = new RegExp(
'#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="' + keyMatchRegExp.source + '"(,IV=\\w+)?)?',
'#EXT-X-KEY:METHOD=(AES-128|NONE)(,URI="[^"]+"(,IV=\\w+)?)?',
'gi'
)
const matchReg = new RegExp(
keyTagMatchRegExp.source + '|' + createFileUrlRegExp('ts', 'gi').source,
'g'
keyTagMatchRegExp.source + '|(?<=#EXTINF:\\d+(\\.\\d+)?,\\n).+',
'gim'
)
const matches = content.match(matchReg)
if (!matches) {
Expand All @@ -243,7 +242,7 @@ class Hls2Mp4 {
for (let i = 0; i < matches.length; i++) {
const matched = matches[i]
if (matched.match(/#EXT-X-KEY/)) {
const matchedKey = matched.match(keyMatchRegExp)?.[0]
const matchedKey = matched.match(/(?<=URI=").+(?=")/)?.[0]
const matchedIV = matched.match(/IV=\w+$/)?.[0]?.replace(/^IV=/, '')
segments.push({
key: matchedKey,
Expand All @@ -261,10 +260,13 @@ class Hls2Mp4 {
}
}

this.totalSegments = segments.reduce((prev, current) => prev + current.segments.length, 0);
this.savedSegments = 0;
const batch = this.tsDownloadConcurrency;
let treatedSegments = 0;
this.totalSegments = segments.reduce(
(prev, current) => prev + current.segments.length,
0
)
this.savedSegments = 0
const batch = this.tsDownloadConcurrency
let treatedSegments = 0

for (const group of segments) {
const total = group.segments.length;
Expand Down Expand Up @@ -345,30 +347,32 @@ class Hls2Mp4 {

public async download(url: string) {
try {
await this.loadFFmpeg();
const m3u8 = await this.downloadM3u8(url);
this.onProgress?.(TaskType.mergeTs, 0);
await this.ffmpeg.exec(['-i', m3u8, '-c', 'copy', 'temp.mp4', '-loglevel', 'debug']);
const data = await this.ffmpeg.readFile('temp.mp4');
this.ffmpeg.terminate();
this.onProgress?.(TaskType.mergeTs, 1);
return data;
await this.loadFFmpeg()
const m3u8 = await this.downloadM3u8(url)
this.onProgress?.(TaskType.mergeTs, 0)
await this.ffmpeg.exec(['-i', m3u8, '-c', 'copy', 'temp.mp4', '-loglevel', 'debug'])
const data = await this.ffmpeg.readFile('temp.mp4')
this.ffmpeg.terminate()
this.onProgress?.(TaskType.mergeTs, 1)
return data
}
catch (err) {
this.ffmpeg.terminate();
this.onError?.(err);
return null;
this.ffmpeg.terminate()
this.onError?.(err)
return null
}
}

public saveToFile(buffer: ArrayBuffer | string, filename: string) {
const objectUrl = URL.createObjectURL(new Blob([buffer], { type: 'video/mp4' }));
const anchor = document.createElement('a');
anchor.href = objectUrl;
anchor.download = filename;
anchor.click();
setTimeout(() => URL.revokeObjectURL(objectUrl), 100);
const objectUrl = URL.createObjectURL(
new Blob([buffer], { type: 'video/mp4' })
)
const anchor = document.createElement('a')
anchor.href = objectUrl
anchor.download = filename
anchor.click()
setTimeout(() => URL.revokeObjectURL(objectUrl), 100)
}
}

export default Hls2Mp4;
export default Hls2Mp4

0 comments on commit 6125462

Please sign in to comment.