UNPKG

@omnimedia/omnitool

Version:

open source video processing tools

126 lines (101 loc) 3.11 kB
import {Comrade} from "@e280/comrade" import {Input, ALL_FORMATS, VideoSampleSink, Output, Mp4OutputFormat, VideoSampleSource, VideoSample, AudioSampleSink, AudioSampleSource, AudioSample, StreamTarget, BlobSource, UrlSource} from "mediabunny" import {DecoderSource, DriverSchematic} from "./schematic.js" const loadSource = async (source: DecoderSource) => { if(source instanceof Blob) { return new BlobSource(source) } else { return new UrlSource(source) } } export const setupDriverWork = ( Comrade.work<DriverSchematic>(shell => ({ async hello() { await shell.host.world() }, async decodeAudio({source, audio, start, end, cancel}) { const input = new Input({ source: await loadSource(source), formats: ALL_FORMATS }) const audioTrack = await input.getPrimaryAudioTrack() const audioDecodable = await audioTrack?.canDecode() const audioWriter = audio.getWriter() if(!audioDecodable || !audioTrack) return const sink = new AudioSampleSink(audioTrack) const samples = sink.samples(start, end) cancel.onmessage = async () => { samples.return() input.dispose() cancel.close() } for await (const sample of samples) { const frame = sample.toAudioData() sample.close() await audioWriter.write(frame) frame.close() } await audioWriter.close() }, async decodeVideo({source, video, start, end, cancel}) { const input = new Input({ source: await loadSource(source), formats: ALL_FORMATS }) const videoTrack = await input.getPrimaryVideoTrack() const videoDecodable = await videoTrack?.canDecode() const videoWriter = video.getWriter() if(!videoDecodable || !videoTrack) return const sink = new VideoSampleSink(videoTrack) const samples = sink.samples(start, end) cancel.onmessage = async () => { await samples.return() cancel.close() } for await (const sample of samples) { const frame = sample.toVideoFrame() sample.close() await videoWriter.write(frame) frame.close() } await videoWriter.close() input.dispose() }, async encode({video, audio, config, writable}) { const output = new Output({ format: new Mp4OutputFormat(), target: new StreamTarget(writable, {chunked: true}) }) async function encodeVideo() { if(!video) return const videoSource = new VideoSampleSource(config.video) output.addVideoTrack(videoSource) for await (const frame of video) { const sample = new VideoSample(frame) await videoSource.add(sample) sample.close() frame.close() } } async function encodeAudio() { if(!audio) return const audioSource = new AudioSampleSource(config.audio) output.addAudioTrack(audioSource) for await (const data of audio) { const sample = new AudioSample(data) await audioSource.add(sample) sample.close() data.close() } } const audioTask = encodeAudio() const videoTask = encodeVideo() await output.start() await Promise.all([audioTask, videoTask]) await output.finalize() }, })) )