UNPKG

mediabunny

Version:

Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.

62 lines (53 loc) 1.97 kB
/*! * 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/. */ import { MP3_FRAME_HEADER_SIZE, getMp3ChannelCount, Mp3FrameHeader, readMp3FrameHeader } from '../../shared/mp3-misc'; import { Reader, readU32Be } from '../reader'; export const readNextMp3FrameHeader = async ( reader: Reader, startPos: number, until: number | null, ref: Mp3FrameHeader | null = null, ): Promise<{ header: Mp3FrameHeader; startPos: number; } | null> => { const CHUNK_SIZE = 2 ** 16; // So we don't need to grab thousands of slices let currentPos = startPos; while (until === null || currentPos < until) { const maxLength = until !== null ? Math.min(CHUNK_SIZE, until - currentPos) : CHUNK_SIZE; let slice = reader.requestSliceRange(currentPos, MP3_FRAME_HEADER_SIZE, maxLength); if (slice instanceof Promise) slice = await slice; if (!slice || slice.length < MP3_FRAME_HEADER_SIZE) break; while (slice.remainingLength >= MP3_FRAME_HEADER_SIZE) { const posBeforeRead = slice.filePos; const word = readU32Be(slice); const remainingBytes = reader.fileSize !== null ? reader.fileSize - currentPos : null; const result = readMp3FrameHeader(word, remainingBytes); if ( result.header && (!ref || ( // This condition helps us recover malformed streams // https://stackoverflow.com/a/20884944 result.header.sampleRate === ref.sampleRate && result.header.mpegVersionId === ref.mpegVersionId && result.header.layer === ref.layer && getMp3ChannelCount(result.header.channel) === getMp3ChannelCount(ref.channel) )) ) { return { header: result.header, startPos: currentPos }; } slice.filePos = posBeforeRead + result.bytesAdvanced; currentPos = slice.filePos; } } return null; };