From 05ae21e5ea5aba9c1822601887a11c0c001684a1 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 9 Mar 2026 10:19:01 +0100 Subject: [PATCH 1/2] Add EncodedPacketSink.getFirstKeyPacket() (used to fix #314) --- docs/guide/media-sinks.md | 6 +++++- src/media-sink.ts | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/docs/guide/media-sinks.md b/docs/guide/media-sinks.md index 84747cb..077630a 100644 --- a/docs/guide/media-sinks.md +++ b/docs/guide/media-sinks.md @@ -97,9 +97,13 @@ await sink.getKeyPacket(5); // => EncodedPacket | null When retrieving a packet using a timestamp, the last packet (in [presentation order](#decode-vs-presentation-order)) with a timestamp less than or equal to the search timestamp will be returned. The methods return `null` if there exists no such packet. -There is a special method for retrieving the first packet (in [decode order](#decode-vs-presentation-order)): +There are special methods for retrieving the first packet (in [decode order](#decode-vs-presentation-order)): ```ts await sink.getFirstPacket(); // => EncodedPacket | null + +// The first packet is typically a key frame, but this is not required. +// This method returns the first key frame: +await sink.getFirstKeyPacket(); // => EncodedPacket | null ``` The last packet (in [presentation order](#decode-vs-presentation-order)) can be retrieved like so: ```ts diff --git a/src/media-sink.ts b/src/media-sink.ts index 7054f97..dd039e2 100644 --- a/src/media-sink.ts +++ b/src/media-sink.ts @@ -144,6 +144,23 @@ export class EncodedPacketSink { return maybeFixPacketType(this._track, this._track._backing.getFirstPacket(options), options); } + /** Retrieves the track's first key packet (in decode order), or null if it has no key packets. */ + async getFirstKeyPacket(options: PacketRetrievalOptions = {}) { + validatePacketRetrievalOptions(options); + + const firstPacket = await this.getFirstPacket(options); + if (!firstPacket) { + return null; + } + + if (firstPacket.type === 'key') { + // Great + return firstPacket; + } + + return this.getNextKeyPacket(firstPacket, options); + } + /** * Retrieves the packet corresponding to the given timestamp, in seconds. More specifically, returns the last packet * (in presentation order) with a start timestamp less than or equal to the given timestamp. This method can be @@ -476,7 +493,7 @@ export abstract class BaseMediaSampleSink< const packetSink = this._createPacketSink(); const keyPacket = await packetSink.getKeyPacket(startTimestamp, { verifyKeyPackets: true }) - ?? await packetSink.getFirstPacket(); + ?? await packetSink.getFirstKeyPacket({ verifyKeyPackets: true }); let currentPacket: EncodedPacket | null = keyPacket; From c4bce00c4fd3ebc206a7d3b661e8513e7142b87b Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:04:57 +0100 Subject: [PATCH 2/2] Bump minor --- package-lock.json | 18 +++++++++--------- package.json | 2 +- packages/aac-encoder/package.json | 2 +- packages/ac3/package.json | 2 +- packages/flac-encoder/package.json | 2 +- packages/mp3-encoder/package.json | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index a36ae7a..dc579e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.38.1", + "version": "1.39.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.38.1", + "version": "1.39.0", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7751,9 +7751,9 @@ } }, "node_modules/mediabunny": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.38.0.tgz", - "integrity": "sha512-FiZtTWLY4rmEw4jBx8r5Tk+sE+PcBb03UYUZNv9DujEy9wdmX7JaQOvHNUZLVTxPWT0h+LYmWFnWKRkl4KmzyA==", + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.38.1.tgz", + "integrity": "sha512-iqZjL21WG32qpdlONAyBBnmhLo4EvF+v4wnfe1rXEKT/7ogiYOZnQGL8TZi7QIFV71DSg7a64egFWUgf3oeSYA==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12077,7 +12077,7 @@ }, "packages/aac-encoder": { "name": "@mediabunny/aac-encoder", - "version": "1.38.1", + "version": "1.39.0", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12092,7 +12092,7 @@ }, "packages/ac3": { "name": "@mediabunny/ac3", - "version": "1.38.1", + "version": "1.39.0", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12107,7 +12107,7 @@ }, "packages/flac-encoder": { "name": "@mediabunny/flac-encoder", - "version": "1.38.1", + "version": "1.39.0", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12122,7 +12122,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.38.1", + "version": "1.39.0", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 424c03e..a14fdde 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.38.1", + "version": "1.39.0", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "workspaces": [ diff --git a/packages/aac-encoder/package.json b/packages/aac-encoder/package.json index e25728b..d8916e7 100644 --- a/packages/aac-encoder/package.json +++ b/packages/aac-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/aac-encoder", "author": "Vanilagy", - "version": "1.38.1", + "version": "1.39.0", "description": "AAC encoder extension for Mediabunny, based on FFmpeg.", "main": "./dist/bundles/mediabunny-aac-encoder.mjs", "module": "./dist/bundles/mediabunny-aac-encoder.mjs", diff --git a/packages/ac3/package.json b/packages/ac3/package.json index f353e54..657d9dc 100644 --- a/packages/ac3/package.json +++ b/packages/ac3/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/ac3", "author": "Vanilagy", - "version": "1.38.1", + "version": "1.39.0", "description": "AC-3 and E-AC-3 (Dolby Digital) decoder and encoder extension for Mediabunny, based on FFmpeg.", "main": "./dist/bundles/mediabunny-ac3.mjs", "module": "./dist/bundles/mediabunny-ac3.mjs", diff --git a/packages/flac-encoder/package.json b/packages/flac-encoder/package.json index 4a8da15..f6327eb 100644 --- a/packages/flac-encoder/package.json +++ b/packages/flac-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/flac-encoder", "author": "Vanilagy", - "version": "1.38.1", + "version": "1.39.0", "description": "FLAC encoder extension for Mediabunny, based on libFLAC.", "main": "./dist/bundles/mediabunny-flac-encoder.mjs", "module": "./dist/bundles/mediabunny-flac-encoder.mjs", diff --git a/packages/mp3-encoder/package.json b/packages/mp3-encoder/package.json index 125a384..a7954b8 100644 --- a/packages/mp3-encoder/package.json +++ b/packages/mp3-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/mp3-encoder", "author": "Vanilagy", - "version": "1.38.1", + "version": "1.39.0", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs",