diff --git a/eslint.config.mjs b/eslint.config.mjs index 4f9053d..dcc3101 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -48,6 +48,7 @@ export default tseslint.config( 'eslint.config.mjs', 'docs/.vitepress/cache', 'test/public', + 'testfiles_temp' ] } ); diff --git a/hls-sketch.ts b/hls-sketch.ts deleted file mode 100644 index 34f73c5..0000000 --- a/hls-sketch.ts +++ /dev/null @@ -1,21 +0,0 @@ -const hlsInput = new ManifestInput({ - source: new UrlSource('https://example.com/playlist.m3u8'), - formats: [HLS], -}); - -const variants = await hlsInput.getVariants(); -const bestVariant = await hlsInput.getPrimaryVariant(); -const qualityVariant = await hlsInput.getVariantFor('1080p'); // In spirit - -bestVariant.tracks; // ? -bestVariant.bitrate; // ? -bestVariant.isLive(); // ? - -const input = variant.toInput(); // => Input -const segments = variant.getSegments(); // => Segments[]? - -const segment = variant.getFirstSegment(); -segment.path; // => string (for example 'segment1.ts') -segment.timestamp; // => 10 -segment.duration; // 5 -segment.toInput(); // => Input diff --git a/src/custom-coder.ts b/src/custom-coder.ts index e2a558d..3661d3a 100644 --- a/src/custom-coder.ts +++ b/src/custom-coder.ts @@ -7,6 +7,8 @@ */ import { AudioCodec, VideoCodec } from './codec'; +import { canDecodeAudioMemo, canDecodeVideoMemo } from './decode'; +import { canEncodeAudioMemo, canEncodeVideoMemo } from './encode'; import { MaybePromise } from './misc'; import { EncodedPacket } from './packet'; import { AudioSample, VideoSample } from './sample'; @@ -152,6 +154,7 @@ export const registerDecoder = (decoder: typeof CustomVideoDecoder | typeof Cust } customVideoDecoders.push(casted); + canDecodeVideoMemo.clear(); } else if (decoder.prototype instanceof CustomAudioDecoder) { const casted = decoder as typeof CustomAudioDecoder; @@ -161,6 +164,7 @@ export const registerDecoder = (decoder: typeof CustomVideoDecoder | typeof Cust } customAudioDecoders.push(casted); + canDecodeAudioMemo.clear(); } else { throw new TypeError('Decoder must be a CustomVideoDecoder or CustomAudioDecoder.'); } @@ -182,6 +186,7 @@ export const registerEncoder = (encoder: typeof CustomVideoEncoder | typeof Cust } customVideoEncoders.push(casted); + canEncodeVideoMemo.clear(); } else if (encoder.prototype instanceof CustomAudioEncoder) { const casted = encoder as typeof CustomAudioEncoder; @@ -191,6 +196,7 @@ export const registerEncoder = (encoder: typeof CustomVideoEncoder | typeof Cust } customAudioEncoders.push(casted); + canEncodeAudioMemo.clear(); } else { throw new TypeError('Encoder must be a CustomVideoEncoder or CustomAudioEncoder.'); } diff --git a/src/decode.ts b/src/decode.ts index e301af1..ca1fb8c 100644 --- a/src/decode.ts +++ b/src/decode.ts @@ -22,8 +22,8 @@ import { import { customAudioDecoders, customVideoDecoders } from './custom-coder'; import { isAllowSharedBufferSource, SetOptional } from './misc'; -const canDecodeVideoMemo = new Map>(); -const canDecodeAudioMemo = new Map>(); +export const canDecodeVideoMemo = new Map>(); +export const canDecodeAudioMemo = new Map>(); const validateVideoDecodingConfig = (codec: VideoCodec, options: SetOptional) => { if (!options || typeof options !== 'object') { diff --git a/src/encode.ts b/src/encode.ts index b3048c9..5de3094 100644 --- a/src/encode.ts +++ b/src/encode.ts @@ -26,8 +26,8 @@ import { isFirefox, MaybePromise, Rotation } from './misc'; import { EncodedPacket } from './packet'; import { AudioSample, CropRectangle, validateCropRectangle, VideoSample } from './sample'; -const canEncodeVideoMemo = new Map>(); -const canEncodeAudioMemo = new Map>(); +export const canEncodeVideoMemo = new Map>(); +export const canEncodeAudioMemo = new Map>(); /** * Configuration object that controls video encoding. Can be used to set codec, quality, and more. diff --git a/src/flac/flac-muxer.ts b/src/flac/flac-muxer.ts index 23db6de..e3bcb5a 100644 --- a/src/flac/flac-muxer.ts +++ b/src/flac/flac-muxer.ts @@ -49,16 +49,16 @@ export class FlacMuxer extends Muxer { super(output); this.format = format; - - if (this.format._options.appendOnly) { - this.writer.ensureMonotonicity(); - } } async start() { const release = await this.mutex.acquire(); this.writer = await this.output._getRootWriter(); + if (this.format._options.appendOnly) { + this.writer.ensureMonotonicity(); + } + this.writer.write(FLAC_HEADER); release(); diff --git a/src/hls/hls-demuxer.ts b/src/hls/hls-demuxer.ts index 503b0c1..015d4fd 100644 --- a/src/hls/hls-demuxer.ts +++ b/src/hls/hls-demuxer.ts @@ -1,3 +1,11 @@ +/*! + * 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 { AUDIO_CODECS, AudioCodec, inferCodecFromCodecString, MediaCodec, VIDEO_CODECS, VideoCodec } from '../codec'; import { Demuxer, DurationMetadataRequestOptions } from '../demuxer'; import { Input } from '../input'; diff --git a/src/hls/hls-misc.ts b/src/hls/hls-misc.ts index dce2e15..db583c3 100644 --- a/src/hls/hls-misc.ts +++ b/src/hls/hls-misc.ts @@ -1,3 +1,11 @@ +/*! + * 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/. + */ + export const canIgnoreLine = (line: string) => line.length === 0 || (line.startsWith('#') && !line.startsWith('#EXT')); export class AttributeList { diff --git a/src/hls/hls-muxer.ts b/src/hls/hls-muxer.ts index a38792b..7c74b43 100644 --- a/src/hls/hls-muxer.ts +++ b/src/hls/hls-muxer.ts @@ -1,3 +1,11 @@ +/*! + * 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 { MediaCodec, validateAudioChunkMetadata, validateVideoChunkMetadata } from '../codec'; import { EncodedAudioPacketSource, EncodedVideoPacketSource } from '../media-source'; import { arrayArgmax, assert, findLastIndex, joinPaths, textEncoder, toArray, UNDETERMINED_LANGUAGE } from '../misc'; diff --git a/src/hls/hls-segmented-input.ts b/src/hls/hls-segmented-input.ts index 7eb7e09..80ef1d8 100644 --- a/src/hls/hls-segmented-input.ts +++ b/src/hls/hls-segmented-input.ts @@ -1,3 +1,11 @@ +/*! + * 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 { AES_128_BLOCK_SIZE, createAes128CbcDecryptStream } from '../aes'; import { ENCRYPTION_KEY_CACHE_GROUP, Input } from '../input'; import { Segment, SegmentedInput, SegmentRetrievalOptions } from '../segmented-input'; diff --git a/src/resample.ts b/src/resample.ts index 19c4606..727492d 100644 --- a/src/resample.ts +++ b/src/resample.ts @@ -1,3 +1,11 @@ +/*! + * 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 { assert } from './misc'; import { AudioSample } from './sample'; diff --git a/test/browser/flac.test.ts b/test/browser/flac.test.ts index ddc065b..ef57adb 100644 --- a/test/browser/flac.test.ts +++ b/test/browser/flac.test.ts @@ -52,7 +52,7 @@ test('can convert a .flac to .wav', async () => { assert(outputTrack); const duration = await outputTrack.computeDuration(); - expect(duration).toBe(19.71428571428571); + expect(duration).toBe(19.714285714285715); const tags = await outputAsInput.getMetadataTags(); expect(tags.raw).toEqual({ IART: 'Samples Files', diff --git a/test/node/disposition.test.ts b/test/node/disposition.test.ts index 18e0b2e..faa4871 100644 --- a/test/node/disposition.test.ts +++ b/test/node/disposition.test.ts @@ -41,6 +41,7 @@ test('Default track disposition', async () => { original: false, hearingImpaired: false, visuallyImpaired: false, + primary: false, commentary: false, }); }); @@ -87,6 +88,7 @@ test('Customized track disposition', async () => { original: true, hearingImpaired: true, visuallyImpaired: true, + primary: false, commentary: true, }); }); diff --git a/test/node/flac.test.ts b/test/node/flac.test.ts index f31e19c..f00befd 100644 --- a/test/node/flac.test.ts +++ b/test/node/flac.test.ts @@ -21,7 +21,7 @@ test('can loop over all samples', async () => { const track = await input.getPrimaryAudioTrack(); assert(track); - expect(await track.computeDuration()).toEqual(19.71428571428571); + expect(await track.computeDuration()).toEqual(19.714285714285715); expect(await track.getDecoderConfig()).toEqual({ codec: 'flac', numberOfChannels: 2,