diff --git a/README.md b/README.md index 6190757..8b2cac5 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ const { title, artist, album } = await input.getMetadataTags(); ### Create new media files ```js -import { Output, Mp4OutputFormat, BufferTarget, CanvasSource, QUALITY_HIGH } from 'mediabunny'; +import { Output, Mp4OutputFormat, BufferTarget, CanvasSource, Quality } from 'mediabunny'; const output = new Output({ format: new Mp4OutputFormat(), @@ -140,7 +140,7 @@ const output = new Output({ // Add a video track backed by a canvas element const videoSource = new CanvasSource(canvas, { codec: 'avc', - bitrate: QUALITY_HIGH, + bitrate: new Quality('high'), }); output.addVideoTrack(videoSource); diff --git a/dev/mux.html b/dev/mux.html index e619bb9..1c39112 100644 --- a/dev/mux.html +++ b/dev/mux.html @@ -47,7 +47,7 @@ format = new Mediabunny.MkvOutputFormat(); format = new Mediabunny.MovOutputFormat(); format = new Mediabunny.Mp4OutputFormat({ fastStart: 'reserve' }); - format = new Mediabunny.WebMOutputFormat(); + format = new Mediabunny.Mp4OutputFormat(); let target = new Mediabunny.BufferTarget(); /* @@ -118,21 +118,21 @@ */ let videoSource = new Mediabunny.CanvasSource(canvas, { - codec: 'vp9', + codec: 'avc', //fullCodecString: 'avc1.42001f', bitrate: 1e6, alpha: 'keep', onEncoderConfig: console.log, }); let audioSource = new Mediabunny.AudioBufferSource({ - codec: 'opus', + codec: 'aac', bitrate: 128e3, }); let subtitleSource = new Mediabunny.TextSubtitleSource('webvtt'); output.addVideoTrack(videoSource, { languageCode: 'eng', name: 'Mononoké', maximumPacketCount: 100 }); output.addAudioTrack(audioSource, { name: 'Yooo', maximumPacketCount: 1000 }); - //output.addSubtitleTrack(subtitleSource); + output.addSubtitleTrack(subtitleSource); output.start(); @@ -191,8 +191,8 @@ Testing... <00:17.350>One... <00:18.125>Two... 9. justify (bottom, right). `; - //subtitleSource.add(simpleWebvttFile); - //subtitleSource.close(); + subtitleSource.add(simpleWebvttFile); + subtitleSource.close(); const p = document.createElement('p'); document.body.append(p); @@ -216,5 +216,5 @@ Testing... <00:17.350>One... <00:18.125>Two... await output.finalize(); console.log(target); - //download(new Blob([target.buffer]), 'test' + format.fileExtension); + download(new Blob([target.buffer]), 'test' + format.fileExtension); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 038bc45..96347fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.52.2", + "version": "1.52.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "workspaces": [ ".", @@ -12954,7 +12954,7 @@ }, "packages/aac-encoder": { "name": "@mediabunny/aac-encoder", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12969,7 +12969,7 @@ }, "packages/ac3": { "name": "@mediabunny/ac3", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12984,7 +12984,7 @@ }, "packages/flac-encoder": { "name": "@mediabunny/flac-encoder", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12999,7 +12999,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -13014,7 +13014,7 @@ }, "packages/prores": { "name": "@mediabunny/prores", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "dependencies": { "turbores": "^1.2.2" @@ -13029,10 +13029,10 @@ }, "packages/server": { "name": "@mediabunny/server", - "version": "1.52.2", + "version": "1.52.3", "license": "MPL-2.0", "dependencies": { - "@mediabunny/prores": "^1.52.2", + "@mediabunny/prores": "^1.52.3", "node-av": "^6.0.0" }, "funding": { diff --git a/package.json b/package.json index 7558e81..249fda3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.52.2", + "version": "1.52.3", "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 81a2985..46a548e 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.52.2", + "version": "1.52.3", "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 a1d89d7..2c65a25 100644 --- a/packages/ac3/package.json +++ b/packages/ac3/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/ac3", "author": "Vanilagy", - "version": "1.52.2", + "version": "1.52.3", "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 8472f91..d0575cc 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.52.2", + "version": "1.52.3", "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 280a91c..f13e6c6 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.52.2", + "version": "1.52.3", "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/packages/prores/package.json b/packages/prores/package.json index 97379da..e726934 100644 --- a/packages/prores/package.json +++ b/packages/prores/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/prores", "author": "Vanilagy", - "version": "1.52.2", + "version": "1.52.3", "description": "Apple ProRes decoder extension for Mediabunny, based on TurboRes.", "main": "./dist/bundles/mediabunny-prores.mjs", "module": "./dist/bundles/mediabunny-prores.mjs", diff --git a/packages/server/package.json b/packages/server/package.json index e2e3bb0..ac938ba 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/server", "author": "Vanilagy", - "version": "1.52.2", + "version": "1.52.3", "description": "Adds full video and audio decoder and encoder support to Mediabunny for use in server-side environments (Node, Bun, Deno). Based on NodeAV.", "main": "./dist/bundles/mediabunny-server.cjs", "module": "./dist/bundles/mediabunny-server.mjs", @@ -35,7 +35,7 @@ }, "dependencies": { "node-av": "^6.0.0", - "@mediabunny/prores": "^1.52.2" + "@mediabunny/prores": "^1.52.3" }, "peerDependencies": { "mediabunny": "^1.45.0" diff --git a/src/isobmff/isobmff-boxes.ts b/src/isobmff/isobmff-boxes.ts index ebbc3a9..57fea8d 100644 --- a/src/isobmff/isobmff-boxes.ts +++ b/src/isobmff/isobmff-boxes.ts @@ -493,6 +493,17 @@ export const tkhd = ( flags |= 0x1; // Track enabled } + // Set the alternate group based on the track type; this mirror's how FFmpeg does it. A more advanced version would + // determine the alternate groups based on the actual track pairability graph. Note that it appears important that + // video get assigned to group 0, see https://github.com/Vanilagy/mediabunny/issues/454. + const alternateGroup = trackData.type === 'video' + ? 0 + : trackData.type === 'audio' + ? 1 + : trackData.type === 'subtitle' + ? 2 + : assertNever(trackData); + return fullBox('tkhd', +needsU64, flags, [ u32OrU64(creationTime), // Creation time u32OrU64(creationTime), // Modification time @@ -501,7 +512,7 @@ export const tkhd = ( u32OrU64(durationInGlobalTimescale), // Duration Array(8).fill(0), // Reserved u16(0), // Layer - u16(trackData.track.id), // Alternate group + u16(alternateGroup), // Alternate group fixed_8_8(trackData.type === 'audio' ? 1 : 0), // Volume u16(0), // Reserved matrixToBytes(matrix), // Matrix diff --git a/src/output.ts b/src/output.ts index 505e732..44f1a49 100644 --- a/src/output.ts +++ b/src/output.ts @@ -830,7 +830,8 @@ export class Output< return this._startPromise = (async () => { this.state = 'started'; - const release = await this._mutex.acquire(); + // We want to call muxer.start immediately, so we avoid using an await here + const releasePromise = this._mutex.acquire(); try { await this._muxer.start(); @@ -838,7 +839,7 @@ export class Output< const promises = this.tracks.map(track => track.source._start()); await Promise.all(promises); } finally { - release(); + (await releasePromise)(); } })(); }