From 48979b863831fee41c865d3d1c7b0f710c0cf347 Mon Sep 17 00:00:00 2001 From: David Halls Date: Sun, 11 Jul 2021 17:43:24 +0100 Subject: [PATCH] Remove a layer of Worker --- site/hls-worker.js | 99 ------------------------------------- site/hls.js | 38 +++++++------- site/webm-destination.js | 104 +++++++++++++++++++++++++++++++++++++++ webm-muxer.js | 2 +- 4 files changed, 122 insertions(+), 121 deletions(-) delete mode 100644 site/hls-worker.js create mode 100644 site/webm-destination.js diff --git a/site/hls-worker.js b/site/hls-worker.js deleted file mode 100644 index 7d1d6d7..0000000 --- a/site/hls-worker.js +++ /dev/null @@ -1,99 +0,0 @@ -let ffmpeg_worker; -let ffmpeg_args; -let base_url; - -function onerror(e) { - if (ffmpeg_worker) { - console.error(e); - self.postMessage({ - type: 'error', - detail: e.message - }); - } -} - -function ffmpeg_onmessage(e) { - const msg = e.data; - switch (msg.type) { - case 'ready': - this.postMessage({ - type: 'run', - arguments: [ - '-loglevel', 'debug', - ...ffmpeg_args, - '-f', 'hls', // use hls encoder - '-hls_time', '2', // 2 second HLS chunks - '-hls_segment_type', 'mpegts', // MPEG2-TS muxer - '-hls_list_size', '2', // two chunks in the list at a time - '-hls_flags', 'split_by_time', - '/outbound/output.m3u8' // path to media playlist file in virtual FS, - // must be under /outbound - ], - MEMFS: [ - { name: 'stream1' }, - { name: 'stream2' } - ] - }); - break; - case 'stdout': - console.log(msg.data); - break; - case 'stderr': - console.error(msg.data); - break; - case 'error': - case 'abort': - onerror(msg.data); - break; - case 'start-stream': - this.postMessage({ - type: 'base-url', - data: base_url - }); - self.postMessage(msg); - break; - case 'exit': - ffmpeg_worker = null; - self.postMessage({ type: msg.type, code: msg.data }); - break; - } -} - -onmessage = function (e) { - const msg = e.data; - switch (msg.type) { - case 'start': - ({ ffmpeg_args, base_url } = msg); - ffmpeg_worker = new Worker(msg.ffmpeg_lib_url); - ffmpeg_worker.onerror = onerror; - ffmpeg_worker.onmessage = ffmpeg_onmessage; - break; - case 'end': - if (ffmpeg_worker) { - if (msg.force) { - ffmpeg_worker.terminate(); - self.postMessage({ - type: 'exit', - code: 'force-end' - }); - } else { - ffmpeg_worker.postMessage({ - type: 'stream-end' - }); - } - ffmpeg_worker = null; - } - break; - case 'muxed-data': - if (ffmpeg_worker) { - ffmpeg_worker.postMessage({ - type: 'stream-data', - name: msg.name, - data: msg.data - }, [msg.data]); - } - break; - } -}; - -self.postMessage({ type: 'ready' }); diff --git a/site/hls.js b/site/hls.js index 9958c98..2c04b90 100644 --- a/site/hls.js +++ b/site/hls.js @@ -1,4 +1,5 @@ import { UpdateLimiter } from './update-limiter.js'; +import { WebMDestination } from './webm-destination.js'; const audioBitsPerSecond = 128 * 1000; const videoBitsPerSecond = 2500 * 1000; @@ -74,13 +75,9 @@ export class HLS extends EventTarget { // push encoded data into the ffmpeg worker recorder.ondataavailable = async event => { - if (this.worker) { - const data = await event.data.arrayBuffer(); - this.worker.postMessage({ - type: 'muxed-data', - name: 'stream1', - data - }, [data]); + if (this.destination) { + this.destination.muxed_data(await event.data.arrayBuffer(), + { name: 'stream1' }); } }; @@ -96,16 +93,13 @@ export class HLS extends EventTarget { dummy_processor.connect(context.destination); // start the ffmpeg worker - this.worker = new Worker('./hls-worker.js'); - this.worker.onerror = onerror; - this.worker.onmessage = e => { - const msg = e.data; + this.destination = new WebMDestination(); + this.destination.addEventListener('message', e => { + const msg = e.detail; switch (msg.type) { case 'ready': - this.worker.postMessage({ - type: 'start', + this.destination.start({ ffmpeg_lib_url: this.ffmpeg_lib_url, - base_url: this.base_url, ffmpeg_args: [ '-i', '/work/stream1', '-map', '0:v', @@ -115,7 +109,8 @@ export class HLS extends EventTarget { ['-c:a', 'copy'] : // assume already AAC ['-c:a', 'aac', // re-encode audio as AAC-LC '-b:a', audioBitsPerSecond.toString()]) // set audio bitrate - ] + ], + base_url: this.base_url }); break; @@ -130,8 +125,7 @@ export class HLS extends EventTarget { break; case 'exit': - this.worker.terminate(); - this.worker = null; + this.destination = null; if (recorder.state !== 'inactive') { recorder.stop(); } @@ -140,7 +134,7 @@ export class HLS extends EventTarget { this.dispatchEvent(new CustomEvent(msg.type, { detail: { code: msg.code } })); break; } - }; + }); } webcodecs(video_codec, audio_codec, video_config, audio_config) { @@ -248,7 +242,7 @@ export class HLS extends EventTarget { codec_id: 'A_OPUS' } }, - webm_destination: './hls-worker.js', + webm_destination: './webm-destination.js', muxed_metadata: { name: 'stream1' }, ffmpeg_lib_url: this.ffmpeg_lib_url, base_url: this.base_url, @@ -264,7 +258,9 @@ export class HLS extends EventTarget { } end(force) { - if (this.worker) { + if (this.destination) { + this.destination.end({ force }); + } else if (this.worker) { this.worker.postMessage({ type: 'end', force @@ -273,7 +269,7 @@ export class HLS extends EventTarget { } onerror(e) { - if (this.worker) { + if (this.destination || this.worker) { this.dispatchEvent(new CustomEvent('error', { detail: e })); } }; diff --git a/site/webm-destination.js b/site/webm-destination.js new file mode 100644 index 0000000..cc55f16 --- /dev/null +++ b/site/webm-destination.js @@ -0,0 +1,104 @@ +export class WebMDestination extends EventTarget { + constructor() { + super(); + setTimeout(() => { + this.dispatchEvent(new CustomEvent('message', { detail: { + type: 'ready' + }})); + }, 0); + } + + start({ ffmpeg_lib_url, ffmpeg_args, base_url }) { + this.worker = new Worker(ffmpeg_lib_url); + this.worker.onerror = this.onerror.bind(this); + this.worker.onmessage = e => { + const msg = e.data; + switch (msg.type) { + case 'ready': + this.worker.postMessage({ + type: 'run', + arguments: [ + '-loglevel', 'debug', + ...ffmpeg_args, + '-f', 'hls', // use hls encoder + '-hls_time', '2', // 2 second HLS chunks + '-hls_segment_type', 'mpegts', // MPEG2-TS muxer + '-hls_list_size', '2', // two chunks in the list at a time + '-hls_flags', 'split_by_time', + '/outbound/output.m3u8' // path to media playlist file in virtual FS, + // must be under /outbound + ], + MEMFS: [ + { name: 'stream1' }, + { name: 'stream2' } + ] + }); + break; + case 'stdout': + console.log(msg.data); + break; + case 'stderr': + console.error(msg.data); + break; + case 'error': + case 'abort': + this.onerror(msg.data); + break; + case 'start-stream': + this.worker.postMessage({ + type: 'base-url', + data: base_url + }); + this.dispatchEvent(new CustomEvent('message', { detail: msg })); + break; + case 'exit': + this.worker = null; + this.dispatchEvent(new CustomEvent('message', { detail: { + type: msg.type, + code: msg.data + }})); + this.worker.terminate(); + break; + } + }; + } + + muxed_data(data, { name }) { + if (this.worker) { + this.worker.postMessage({ + type: 'stream-data', + name, + data + }, [data]); + } + } + + end({ force }) { + if (this.worker) { + if (force) { + this.worker.terminate(); + self.postMessage({ + this.dispatchEvent(new CustomEvent('message', { detail: { + type: 'exit', + code: 'force-end' + }})); + }); + } else { + this.worker.postMessage({ + type: 'stream-end' + }); + } + this.worker = null; + } + } + + onerror(e) { + if (this.worker) { + console.error(e); + this.dispatchEvent(new CustomEvent('message', { detail: { + type: 'error', + detail: e.message + }})); + } + } +} diff --git a/webm-muxer.js b/webm-muxer.js index c4c0514..73cb64a 160000 --- a/webm-muxer.js +++ b/webm-muxer.js @@ -1 +1 @@ -Subproject commit c4c051469c3cda09c70ee2f887633d6e079927b2 +Subproject commit 73cb64a9816200348ba421db395158f597375cef