-
Notifications
You must be signed in to change notification settings - Fork 156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(av-cliper): concurrency download for hls-loader #140
Changes from 1 commit
468f987
ee7f424
e790dd2
a820688
f58342b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ import { Parser } from 'm3u8-parser'; | |
/** | ||
* 创建一个 HLS 资源加载器 | ||
*/ | ||
export async function createHLSLoader(m3u8URL: string) { | ||
export async function createHLSLoader(m3u8URL: string, concurrency = 10) { | ||
const parser = new Parser(); | ||
parser.push(await (await fetch(m3u8URL)).text()); | ||
parser.end(); | ||
|
@@ -17,12 +17,64 @@ export async function createHLSLoader(m3u8URL: string) { | |
); | ||
const base = new URL(m3u8URL, location.href); | ||
|
||
const segmentBufferFetchqueue = {} as Record<string, Promise<ArrayBuffer>>; | ||
|
||
async function downloadSegGroup() { | ||
function createTaskQueue(concurrency: number) { | ||
let running = 0; | ||
const queue = [] as Function[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 替换为 |
||
|
||
async function runTask(task: Function) { | ||
queue.push(task); | ||
next(); | ||
} | ||
|
||
async function next() { | ||
if (running < concurrency && queue.length) { | ||
const task = queue.shift(); | ||
running++; | ||
try { | ||
if (task) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 替换为 |
||
await task(); | ||
} | ||
} catch (err) { | ||
console.error(err); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 替换为 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 异常时需要中断流,否则流永远不会结束,且使用方无法感知到错误。 |
||
} | ||
running--; | ||
next(); | ||
} | ||
} | ||
|
||
return runTask; | ||
} | ||
|
||
async function fetchSegmentBufferPromise(url: string) { | ||
return (await fetch(url)).arrayBuffer(); | ||
} | ||
|
||
const runTask = createTaskQueue(concurrency); | ||
|
||
for (const [, gData] of Object.entries(segGroup)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 复用 load 中转换的数据 |
||
for (const [, item] of gData.entries()) { | ||
const url = new URL(item.uri, base).href; | ||
runTask( | ||
() => (segmentBufferFetchqueue[url] = fetchSegmentBufferPromise(url)), | ||
); | ||
} | ||
} | ||
} | ||
|
||
async function getSegmentBuffer(url: string) { | ||
return segmentBufferFetchqueue[url].then((value) => value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 替换为 |
||
} | ||
|
||
return { | ||
/** | ||
* 下载期望时间区间的分配数据,封装成流 | ||
* 每个分片包含一个时间段,实际下载的分片数据时长会略大于期望的时间区间 | ||
*/ | ||
load(expectStartTime = 0, expectEndTime = Infinity) { | ||
downloadSegGroup(); | ||
const filterSegGroup = {} as Record< | ||
string, | ||
{ | ||
|
@@ -86,13 +138,8 @@ export async function createHLSLoader(m3u8URL: string) { | |
); | ||
}, | ||
pull: async (ctrl) => { | ||
ctrl.enqueue( | ||
new Uint8Array( | ||
await ( | ||
await fetch(new URL(segments[segIdx].uri, base).href) | ||
).arrayBuffer(), | ||
), | ||
); | ||
const url = new URL(segments[segIdx].uri, base).href; | ||
ctrl.enqueue(new Uint8Array(await getSegmentBuffer(url))); | ||
segIdx += 1; | ||
if (segIdx >= segments.length) ctrl.close(); | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
参数
concurrency = 10
移到内部,默认不对外开放,若有有需求再讨论开放。可以简化 API 、降低破坏性变更几率。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要,不同业务方期望的并行数量应该是不一样的