streamana/site/mux-receiver.js

115 lines
4.0 KiB
JavaScript
Raw Normal View History

export class MuxReceiver extends EventTarget {
2021-07-12 00:43:24 +08:00
constructor() {
super();
setTimeout(() => {
this.dispatchEvent(new CustomEvent('message', { detail: {
type: 'ready'
}}));
}, 0);
}
2021-10-15 01:07:21 +08:00
start({ ffmpeg_lib_url, ffmpeg_args, base_url, protocol }) {
2021-07-12 00:43:24 +08:00
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: [
'-seekable', '0',
2021-07-12 00:43:24 +08:00
...ffmpeg_args,
2021-10-16 14:37:09 +08:00
...(protocol === 'dash' ? [
'-f', 'dash', // use dash encoder
'-seg_duration', '2', // 2 second segments
'-window_size', '2',
'-streaming', '1',
'-dash_segment_type', 'webm',
'/outbound/output.mpd'
] : [
'-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
])
2021-07-12 00:43:24 +08:00
],
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',
2021-10-15 01:07:21 +08:00
data: base_url,
protocol
2021-07-12 00:43:24 +08:00
});
// falls through
case 'sending':
2021-07-12 00:43:24 +08:00
this.dispatchEvent(new CustomEvent('message', { detail: msg }));
break;
case 'ffexit':
2021-07-12 14:39:30 +08:00
this.worker.terminate();
2021-07-12 00:43:24 +08:00
this.worker = null;
this.dispatchEvent(new CustomEvent('message', { detail: {
type: 'exit',
code: msg.code
2021-07-12 00:43:24 +08:00
}}));
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();
2021-07-12 14:39:30 +08:00
this.worker = null;
this.dispatchEvent(new CustomEvent('message', { detail: {
type: 'exit',
code: 'force-end'
}}));
2021-07-12 00:43:24 +08:00
} else {
this.worker.postMessage({
type: 'stream-end'
});
}
}
}
onerror(e) {
if (this.worker) {
console.error(e);
this.dispatchEvent(new CustomEvent('message', { detail: {
type: 'error',
detail: e.message
}}));
}
}
}