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] 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;