Allow object for tags field in conversion

This commit is contained in:
Vanilagy
2025-09-16 15:10:16 +02:00
parent 7efb092ff5
commit fcec67645a
4 changed files with 55 additions and 47 deletions
+27 -27
View File
@@ -47,23 +47,6 @@
format: outputFormat, format: outputFormat,
target target
}); });
output.setMetadataTags({
title: 'Bigggy',
artist: 'Buck Bunny',
images: [{
data: blobData,
kind: 'coverFront',
mimeType: 'image/jpeg'
}],
trackNumber: 4,
tracksTotal: 10,
discNumber: 5,
discNumberMax: 8,
lyrics: "There's no way\nThat it's not going there",
raw: {
'ENCODER': 'Mediabunny epic own encoder'
}
});
const conversion = await Mediabunny.Conversion.init({ const conversion = await Mediabunny.Conversion.init({
input: new Mediabunny.Input({ input: new Mediabunny.Input({
@@ -109,16 +92,16 @@
*/ */
video: () => ({ video: () => ({
//discard: true, //discard: true,
crop: { //crop: {
left: 0, // left: 0,
top: 0, // top: 0,
width: 500, // width: 500,
height: 500, // height: 500,
}, //},
rotate: 90, //rotate: 90,
width: 200, //width: 200,
height: 500, //height: 500,
fit: 'contain', //fit: 'contain',
//forceTranscode: true, //forceTranscode: true,
//codec: 'avc', //codec: 'avc',
//fit: 'contain', //fit: 'contain',
@@ -141,6 +124,23 @@
//width: 200, //width: 200,
//height: 100, //height: 100,
}), }),
tags: {
title: 'Bigggy',
artist: 'Buck Bunny',
images: [{
data: blobData,
kind: 'coverFront',
mimeType: 'image/jpeg'
}],
trackNumber: 4,
tracksTotal: 10,
discNumber: 5,
discsTotal: 8,
lyrics: "There's no way\nThat it's not going there",
raw: {
'AIGC': 'Mediabunny epic own encoder'
}
},
trim: { trim: {
start: 10, start: 10,
end: 20 end: 20
+1 -6
View File
@@ -14,12 +14,7 @@
source: new Mediabunny.BlobSource(file), source: new Mediabunny.BlobSource(file),
}); });
const audioTrack = await input.getPrimaryAudioTrack(); console.log(await input.getMetadataTags())
const sink = new Mediabunny.EncodedPacketSink(audioTrack);
for await (const packet of sink.packets()) {
console.log(packet);
}
/* /*
const sink = new Mediabunny.EncodedPacketSink(videoTrack); const sink = new Mediabunny.EncodedPacketSink(videoTrack);
+5 -5
View File
@@ -49,7 +49,7 @@ await conversion.execute();
That's it! A `Conversion` simply takes an instance of `Input` and `Output`, then reads the data from the input and writes it to the output. If you're unfamiliar with [`Input`](./reading-media-files) and [`Output`](./writing-media-files), check out their respective guides. That's it! A `Conversion` simply takes an instance of `Input` and `Output`, then reads the data from the input and writes it to the output. If you're unfamiliar with [`Input`](./reading-media-files) and [`Output`](./writing-media-files), check out their respective guides.
::: info ::: info
The `Output` passed to the `Conversion` must be *fresh*; that is, it must have no added tracks and be in the `'pending'` state (not started yet). The `Output` passed to the `Conversion` must be *fresh*; that is, it must have no added tracks or metadata tags and be in the `'pending'` state (not started yet).
::: :::
Unconfigured, the conversion process handles all the details automatically, such as: Unconfigured, the conversion process handles all the details automatically, such as:
@@ -299,17 +299,17 @@ By default, any [descriptive metadata tags](../api/MetadataTags.md) of the input
// Set your own metadata: // Set your own metadata:
const conversion = await Conversion.init({ const conversion = await Conversion.init({
// ... // ...
tags: () => ({ tags: {
title: 're:Turning', title: 're:Turning',
artist: 'Alexander Panos', artist: 'Alexander Panos',
}), },
// ... // ...
}); });
// Or, augment the input's metadata: // Or, augment the input's metadata:
const conversion = await Conversion.init({ const conversion = await Conversion.init({
// ... // ...
tags: inputTags => ({ tags: (inputTags) => ({
...inputTags, // Keep the existing metadata ...inputTags, // Keep the existing metadata
images: [{ // And add cover art images: [{ // And add cover art
data: new Uint8Array(...), data: new Uint8Array(...),
@@ -324,7 +324,7 @@ const conversion = await Conversion.init({
// Or, remove all metadata // Or, remove all metadata
const conversion = await Conversion.init({ const conversion = await Conversion.init({
// ... // ...
tags: () => ({}), tags: {},
// ... // ...
}); });
``` ```
+22 -9
View File
@@ -89,13 +89,13 @@ export type ConversionOptions = {
}; };
/** /**
* A callback that returns or resolves to the descriptive metadata tags that should be written to the output file. * An object or a callback that returns or resolves to an object containing the descriptive metadata tags that
* As input, this function will be passed the tags of the input file, allowing you to modify, augment or extend * should be written to the output file. If a function is passed, it will be passed the tags of the input file as
* them. * its first argument, allowing you to modify, augment or extend them.
* *
* If no function is set, the input's metadata tags will be copied to the output. * If no function is set, the input's metadata tags will be copied to the output.
*/ */
tags?: (inputTags: MetadataTags) => MaybePromise<MetadataTags>; tags?: MetadataTags | ((inputTags: MetadataTags) => MaybePromise<MetadataTags>);
}; };
/** /**
@@ -395,8 +395,12 @@ export class Conversion {
if (!(options.output instanceof Output)) { if (!(options.output instanceof Output)) {
throw new TypeError('options.output must be an Output.'); throw new TypeError('options.output must be an Output.');
} }
if (options.output._tracks.length > 0 || options.output.state !== 'pending') { if (
throw new TypeError('options.output must be fresh: no tracks added and not started.'); options.output._tracks.length > 0
|| Object.keys(options.output._metadataTags).length > 0
|| options.output.state !== 'pending'
) {
throw new TypeError('options.output must be fresh: no tracks or metadata tags added and not started.');
} }
if (typeof options.video !== 'function') { if (typeof options.video !== 'function') {
@@ -426,8 +430,15 @@ export class Conversion {
&& options.trim.start >= options.trim.end) { && options.trim.start >= options.trim.end) {
throw new TypeError('options.trim.start must be less than options.trim.end.'); throw new TypeError('options.trim.start must be less than options.trim.end.');
} }
if (options.tags !== undefined && typeof options.tags !== 'function') { if (
throw new TypeError('options.tags, when provided, must be a function.'); options.tags !== undefined
&& (typeof options.tags !== 'object' || !options.tags)
&& typeof options.tags !== 'function'
) {
throw new TypeError('options.tags, when provided, must be an object or a function.');
}
if (typeof options.tags === 'object') {
validateMetadataTags(options.tags);
} }
this._options = options; this._options = options;
@@ -519,7 +530,9 @@ export class Conversion {
let outputTags: MetadataTags; let outputTags: MetadataTags;
if (this._options.tags) { if (this._options.tags) {
const result = await this._options.tags(inputTags); const result = typeof this._options.tags === 'function'
? await this._options.tags(inputTags)
: this._options.tags;
validateMetadataTags(result); validateMetadataTags(result);
outputTags = result; outputTags = result;