| ; | |
| /*! | |
| * Copyright (c) 2026-present, Vanilagy and contributors | |
| * | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at https://mozilla.org/MPL/2.0/. | |
| */ | |
| var __importDefault = (this && this.__importDefault) || function (mod) { | |
| return (mod && mod.__esModule) ? mod : { "default": mod }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| const aac_1 = __importDefault(require("../build/aac")); | |
| let module; | |
| let modulePromise = null; | |
| let initEncoderFn; | |
| let getEncoderFrameSize; | |
| let getEncoderExtradata; | |
| let getEncoderExtradataSize; | |
| let getEncodeInputPtr; | |
| let sendFrameFn; | |
| let receivePacketFn; | |
| let flushEncoderStartFn; | |
| let resetEncoderFn; | |
| let getEncodedData; | |
| let getEncodedPts; | |
| let getEncodedDuration; | |
| const ensureModule = async () => { | |
| if (!module) { | |
| if (modulePromise) { | |
| return modulePromise; | |
| } | |
| modulePromise = (0, aac_1.default)(); | |
| module = await modulePromise; | |
| modulePromise = null; | |
| initEncoderFn = module.cwrap('init_encoder', 'number', ['number', 'number', 'number']); | |
| getEncoderFrameSize = module.cwrap('get_encoder_frame_size', 'number', ['number']); | |
| getEncoderExtradata = module.cwrap('get_encoder_extradata', 'number', ['number']); | |
| getEncoderExtradataSize = module.cwrap('get_encoder_extradata_size', 'number', ['number']); | |
| getEncodeInputPtr = module.cwrap('get_encode_input_ptr', 'number', ['number', 'number']); | |
| sendFrameFn = module.cwrap('send_frame', 'number', ['number', 'number']); | |
| receivePacketFn = module.cwrap('receive_packet', 'number', ['number']); | |
| flushEncoderStartFn = module.cwrap('flush_encoder_start', null, ['number']); | |
| resetEncoderFn = module.cwrap('reset_encoder', null, ['number']); | |
| getEncodedData = module.cwrap('get_encoded_data', 'number', ['number']); | |
| getEncodedPts = module.cwrap('get_encoded_pts', 'number', ['number']); | |
| getEncodedDuration = module.cwrap('get_encoded_duration', 'number', ['number']); | |
| } | |
| }; | |
| const initEncoder = async (numberOfChannels, sampleRate, bitrate) => { | |
| await ensureModule(); | |
| const ctx = initEncoderFn(numberOfChannels, sampleRate, bitrate); | |
| if (ctx === 0) { | |
| throw new Error('Failed to initialize AAC encoder.'); | |
| } | |
| const frameSize = getEncoderFrameSize(ctx); | |
| const extradataPtr = getEncoderExtradata(ctx); | |
| const extradataSize = getEncoderExtradataSize(ctx); | |
| const extradata = module.HEAPU8.slice(extradataPtr, extradataPtr + extradataSize).buffer; | |
| return { ctx, frameSize, extradata }; | |
| }; | |
| const drainPackets = (ctx) => { | |
| const packets = []; | |
| let size; | |
| while ((size = receivePacketFn(ctx)) > 0) { | |
| const ptr = getEncodedData(ctx); | |
| const encodedData = module.HEAPU8.slice(ptr, ptr + size).buffer; | |
| const pts = Number(getEncodedPts(ctx)); | |
| const duration = getEncodedDuration(ctx); | |
| packets.push({ encodedData, pts, duration }); | |
| } | |
| return packets; | |
| }; | |
| const encode = (ctx, audioData, timestamp) => { | |
| const audioBytes = new Uint8Array(audioData); | |
| const inputPtr = getEncodeInputPtr(ctx, audioBytes.length); | |
| if (inputPtr === 0) { | |
| throw new Error('Failed to allocate encoder input buffer.'); | |
| } | |
| module.HEAPU8.set(audioBytes, inputPtr); | |
| const ret = sendFrameFn(ctx, BigInt(timestamp)); | |
| if (ret < 0) { | |
| throw new Error(`Encode failed with error code ${ret}.`); | |
| } | |
| return drainPackets(ctx); | |
| }; | |
| const onMessage = (data) => { | |
| const { id, command } = data; | |
| const handleCommand = async () => { | |
| try { | |
| let result; | |
| const transferables = []; | |
| switch (command.type) { | |
| case 'init': | |
| { | |
| const { ctx, frameSize, extradata } = await initEncoder(command.data.numberOfChannels, command.data.sampleRate, command.data.bitrate); | |
| result = { type: command.type, ctx, frameSize, extradata }; | |
| transferables.push(extradata); | |
| } | |
| ; | |
| break; | |
| case 'encode': | |
| { | |
| const packets = encode(command.data.ctx, command.data.audioData, command.data.timestamp); | |
| for (const p of packets) { | |
| transferables.push(p.encodedData); | |
| } | |
| result = { type: command.type, packets }; | |
| } | |
| ; | |
| break; | |
| case 'flush': | |
| { | |
| flushEncoderStartFn(command.data.ctx); | |
| const packets = drainPackets(command.data.ctx); | |
| for (const p of packets) { | |
| transferables.push(p.encodedData); | |
| } | |
| resetEncoderFn(command.data.ctx); | |
| result = { type: command.type, packets }; | |
| } | |
| ; | |
| break; | |
| } | |
| const response = { | |
| id, | |
| success: true, | |
| data: result, | |
| }; | |
| sendMessage(response, transferables); | |
| } | |
| catch (error) { | |
| const response = { | |
| id, | |
| success: false, | |
| error, | |
| }; | |
| sendMessage(response); | |
| } | |
| }; | |
| void handleCommand(); | |
| }; | |
| const sendMessage = (data, transferables) => { | |
| if (parentPort) { | |
| parentPort.postMessage(data, transferables ?? []); | |
| } | |
| else { | |
| self.postMessage(data, { transfer: transferables ?? [] }); | |
| } | |
| }; | |
| let parentPort = null; | |
| try { | |
| // We're in Node.js (or a runtime that mimics it) | |
| const workerModule = 'worker_threads'; | |
| // eslint-disable-next-line @stylistic/max-len | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-member-access | |
| parentPort = require(workerModule).parentPort; | |
| } | |
| catch { | |
| // Web worker (browser, Deno), no require available | |
| } | |
| if (parentPort) { | |
| parentPort.on('message', onMessage); | |
| } | |
| else { | |
| self.addEventListener('message', event => onMessage(event.data)); | |
| } | |
| // Prevents the worker for being randomly closed by Firefox | |
| // https://github.com/Vanilagy/mediabunny/issues/435 | |
| setInterval(() => { }, 1000); | |
Xet Storage Details
- Size:
- 6.58 kB
- Xet hash:
- 623f1265a7cddb69b17bcd13c4b57839dd113fe4c2d06cc8e1644c525949201b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.