mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-03 05:43:50 +02:00
Add metadata read/write support to ISOBMFF, add more metadata fields, add raw metadata support
This commit is contained in:
+53
-8
@@ -2,13 +2,16 @@
|
||||
|
||||
export type MediaMetadata = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
artist?: string;
|
||||
album?: string;
|
||||
albumArtist?: string;
|
||||
trackNumber?: number;
|
||||
trackNumberMax?: number;
|
||||
discNumber?: number;
|
||||
discNumberMax?: number;
|
||||
genre?: string;
|
||||
releasedAt?: Date;
|
||||
date?: Date;
|
||||
lyrics?: string;
|
||||
images?: {
|
||||
data: Uint8Array;
|
||||
@@ -18,8 +21,13 @@ export type MediaMetadata = {
|
||||
description?: string;
|
||||
}[];
|
||||
comment?: string;
|
||||
raw?: Record<string, string | Uint8Array | RichImageData | null>;
|
||||
};
|
||||
|
||||
export class RichImageData {
|
||||
constructor(public data: Uint8Array, public mimeType: string) {}
|
||||
}
|
||||
|
||||
export const validateMediaMetadata = (metadata: MediaMetadata) => {
|
||||
if (!metadata || typeof metadata !== 'object') {
|
||||
throw new TypeError('metadata must be an object.');
|
||||
@@ -27,6 +35,9 @@ export const validateMediaMetadata = (metadata: MediaMetadata) => {
|
||||
if (metadata.title !== undefined && typeof metadata.title !== 'string') {
|
||||
throw new TypeError('metadata.title, when provided, must be a string.');
|
||||
}
|
||||
if (metadata.description !== undefined && typeof metadata.description !== 'string') {
|
||||
throw new TypeError('metadata.description, when provided, must be a string.');
|
||||
}
|
||||
if (metadata.artist !== undefined && typeof metadata.artist !== 'string') {
|
||||
throw new TypeError('metadata.artist, when provided, must be a string.');
|
||||
}
|
||||
@@ -39,21 +50,30 @@ export const validateMediaMetadata = (metadata: MediaMetadata) => {
|
||||
if (metadata.trackNumber !== undefined && (!Number.isInteger(metadata.trackNumber) || metadata.trackNumber <= 0)) {
|
||||
throw new TypeError('metadata.trackNumber, when provided, must be a positive integer.');
|
||||
}
|
||||
if (
|
||||
metadata.trackNumberMax !== undefined
|
||||
&& (!Number.isInteger(metadata.trackNumberMax) || metadata.trackNumberMax <= 0)
|
||||
) {
|
||||
throw new TypeError('metadata.trackNumberMax, when provided, must be a positive integer.');
|
||||
}
|
||||
if (metadata.discNumber !== undefined && (!Number.isInteger(metadata.discNumber) || metadata.discNumber <= 0)) {
|
||||
throw new TypeError('metadata.discNumber, when provided, must be a positive integer.');
|
||||
}
|
||||
if (
|
||||
metadata.discNumberMax !== undefined
|
||||
&& (!Number.isInteger(metadata.discNumberMax) || metadata.discNumberMax <= 0)
|
||||
) {
|
||||
throw new TypeError('metadata.discNumberMax, when provided, must be a positive integer.');
|
||||
}
|
||||
if (metadata.genre !== undefined && typeof metadata.genre !== 'string') {
|
||||
throw new TypeError('metadata.genre, when provided, must be a string.');
|
||||
}
|
||||
if (metadata.releasedAt !== undefined && !(metadata.releasedAt instanceof Date)) {
|
||||
throw new TypeError('metadata.releasedAt, when provided, must be a Date.');
|
||||
if (metadata.date !== undefined && !(metadata.date instanceof Date)) {
|
||||
throw new TypeError('metadata.date, when provided, must be a Date.');
|
||||
}
|
||||
if (metadata.lyrics !== undefined && typeof metadata.lyrics !== 'string') {
|
||||
throw new TypeError('metadata.lyrics, when provided, must be a string.');
|
||||
}
|
||||
if (metadata.comment !== undefined && typeof metadata.comment !== 'string') {
|
||||
throw new TypeError('metadata.comment, when provided, must be a string.');
|
||||
}
|
||||
if (metadata.images !== undefined) {
|
||||
if (!Array.isArray(metadata.images)) {
|
||||
throw new TypeError('metadata.images, when provided, must be an array.');
|
||||
@@ -73,18 +93,43 @@ export const validateMediaMetadata = (metadata: MediaMetadata) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (metadata.comment !== undefined && typeof metadata.comment !== 'string') {
|
||||
throw new TypeError('metadata.comment, when provided, must be a string.');
|
||||
}
|
||||
if (metadata.raw !== undefined) {
|
||||
if (!metadata.raw || typeof metadata.raw !== 'object') {
|
||||
throw new TypeError('metadata.raw, when provided, must be an object.');
|
||||
}
|
||||
|
||||
for (const value of Object.values(metadata.raw)) {
|
||||
if (
|
||||
value !== null
|
||||
&& typeof value !== 'string'
|
||||
&& !(value instanceof Uint8Array)
|
||||
&& !(value instanceof RichImageData)
|
||||
) {
|
||||
throw new TypeError(
|
||||
'Each value in metadata.raw must be a string, Uint8Array, RichImageData, or null.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const mediaMetadataIsEmpty = (metadata: MediaMetadata) => {
|
||||
return metadata.title === undefined
|
||||
&& metadata.description === undefined
|
||||
&& metadata.artist === undefined
|
||||
&& metadata.album === undefined
|
||||
&& metadata.albumArtist === undefined
|
||||
&& metadata.trackNumber === undefined
|
||||
&& metadata.trackNumberMax === undefined
|
||||
&& metadata.discNumber === undefined
|
||||
&& metadata.discNumberMax === undefined
|
||||
&& metadata.genre === undefined
|
||||
&& metadata.releasedAt === undefined
|
||||
&& metadata.date === undefined
|
||||
&& metadata.lyrics === undefined
|
||||
&& (!metadata.images || metadata.images.length === 0)
|
||||
&& metadata.comment === undefined
|
||||
&& (!metadata.images || metadata.images.length === 0);
|
||||
&& (metadata.raw === undefined || Object.keys(metadata.raw).length === 0);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user