diff --git a/dev/demux.html b/dev/demux.html
index c9c5fd5..04d1e43 100644
--- a/dev/demux.html
+++ b/dev/demux.html
@@ -8,15 +8,6 @@
document.body.append(fileInput);
fileInput.addEventListener('change', async () => {
- const videoUrl = "https://upload.wikimedia.org/wikipedia/commons/5/53/1941._%D0%9A%D0%BE%D0%BD%D1%91%D0%BA-%D0%B3%D0%BE%D1%80%D0%B1%D1%83%D0%BD%D0%BE%D0%BA.webm"
- const source = new Mediabunny.UrlSource(videoUrl)
- const input = new Mediabunny.Input({ formats: Mediabunny.ALL_FORMATS, source });
-
- const videoTrack = await input.getPrimaryVideoTrack();
-
- console.log(videoTrack);
-
- /*
const file = fileInput.files[0];
const source = new Mediabunny.BlobSource(file);
@@ -25,6 +16,15 @@
source
});
+ const videoTrack = await input.getPrimaryVideoTrack();
+ const sink = new Mediabunny.EncodedPacketSink(videoTrack);
+
+ for await (const packet of sink.packets(undefined, undefined, { verifyKeyPackets: false })) {
+ console.log(packet);
+ if (packet.timestamp >= 2.4) break;
+ }
+
+ /*
const audioTrack = await input.getPrimaryAudioTrack();
const sink = new Mediabunny.EncodedPacketSink(audioTrack);
diff --git a/package-lock.json b/package-lock.json
index 7ea184f..0655037 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "mediabunny",
- "version": "1.7.1",
+ "version": "1.7.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mediabunny",
- "version": "1.7.1",
+ "version": "1.7.2",
"license": "MPL-2.0",
"workspaces": [
"packages/*"
@@ -5900,9 +5900,9 @@
}
},
"node_modules/mediabunny": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.7.0.tgz",
- "integrity": "sha512-QcTdptOtvjAHb4KQpgWWWHRS0+DgGwTXelTwPWaZwQu85iYy11bzsLS4e29rfH4nLL/eq8K/dBsjj1LuApc2Qw==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.7.1.tgz",
+ "integrity": "sha512-y9s+Vf6TLhXeVjvlJFSmHRrwUQi2CJCMhxthm6nfhBO1XHJhcOqNOxu4CjhYyjoWgVZB5pkPKyWgZxpPOZfglQ==",
"license": "MPL-2.0",
"peer": true,
"workspaces": [
@@ -9017,7 +9017,7 @@
},
"packages/mp3-encoder": {
"name": "@mediabunny/mp3-encoder",
- "version": "1.7.1",
+ "version": "1.7.2",
"license": "MPL-2.0",
"devDependencies": {
"@types/emscripten": "^1.40.1"
diff --git a/package.json b/package.json
index 327ea65..709c529 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "mediabunny",
"author": "Vanilagy",
- "version": "1.7.1",
+ "version": "1.7.2",
"description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
"type": "module",
"workspaces": [
diff --git a/packages/mp3-encoder/package.json b/packages/mp3-encoder/package.json
index 5b2b163..14f4776 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.7.1",
+ "version": "1.7.2",
"description": "MP3 encoder extension for Mediabunny, based on LAME.",
"main": "./dist/bundles/mediabunny-mp3-encoder.mjs",
"module": "./dist/bundles/mediabunny-mp3-encoder.mjs",
diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts
index 20bcf42..80c1dc2 100644
--- a/src/isobmff/isobmff-demuxer.ts
+++ b/src/isobmff/isobmff-demuxer.ts
@@ -1459,6 +1459,12 @@ export class IsobmffDemuxer extends Demuxer {
const sampleIndex = this.metadataReader.readU32() - 1; // Convert to 0-indexed
track.sampleTable.keySampleIndices.push(sampleIndex);
}
+
+ if (track.sampleTable.keySampleIndices[0] !== 0) {
+ // Some files don't mark the first sample a key sample, which is basically almost always incorrect.
+ // Here, we correct for that mistake:
+ track.sampleTable.keySampleIndices.unshift(0);
+ }
}; break;
case 'stsc': {
diff --git a/src/media-sink.ts b/src/media-sink.ts
index aec70e7..6c4de94 100644
--- a/src/media-sink.ts
+++ b/src/media-sink.ts
@@ -1248,9 +1248,15 @@ class AudioDecoderWrapper extends DecoderWrapper {
super(onSample, onError);
const sampleHandler = (sample: AudioSample) => {
- const sampleRate = decoderConfig.sampleRate;
+ if (sample.numberOfFrames === 0) {
+ // We skip zero-data (empty) AudioSamples. These are sometimes emitted, for example, by Firefox when it
+ // decodes Vorbis (at the start).
+ sample.close();
+ return;
+ }
// Round the timestamp to the sample rate
+ const sampleRate = decoderConfig.sampleRate;
sample.setTimestamp(Math.round(sample.timestamp * sampleRate) / sampleRate);
onSample(sample);
diff --git a/src/media-source.ts b/src/media-source.ts
index 2ae14db..3860552 100644
--- a/src/media-source.ts
+++ b/src/media-source.ts
@@ -158,7 +158,8 @@ export class EncodedVideoPacketSource extends VideoSource {
}
/**
- * Adds an encoded packet to the output video track.
+ * Adds an encoded packet to the output video track. Packets must be added in *decode order*, while a packet's
+ * timestamp must be its *presentation timestamp*. B-frames are handled automatically.
*
* @param meta - Additional metadata from the encoder. You should pass this for the first call, including a valid
* decoder config.
@@ -788,7 +789,7 @@ export class EncodedAudioPacketSource extends AudioSource {
}
/**
- * Adds an encoded packet to the output audio track.
+ * Adds an encoded packet to the output audio track. Packets must be added in *decode order*.
*
* @param meta - Additional metadata from the encoder. You should pass this for the first call, including a valid
* decoder config.