From 6a12a363d19bb0e2f64f01c08518b110a857e54f Mon Sep 17 00:00:00 2001 From: Steven Vandevelde Date: Fri, 9 Feb 2024 19:10:19 +0100 Subject: [PATCH] fix: default to music-metadata because mediainfo.js has encoding issues --- package-lock.json | 28 ++++++++++++++++++++++++++++ package.json | 2 ++ src/Javascript/processing.ts | 34 ++++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index c278d2cf..f7be86f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,10 @@ "@oddjs/odd": "^0.37.2", "@tokenizer/http": "^0.6.2", "elm-taskport": "^2.0.1", + "encoding-japanese": "^2.0.0", "fast-text-encoding": "^1.0.6", "file-saver": "^2.0.2", + "jschardet": "^3.0.0", "jszip": "^3.7.1", "load-script2": "^2.0.5", "localforage": "^1.10.0", @@ -3195,6 +3197,14 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/encoding-japanese": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", + "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==", + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -4942,6 +4952,14 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jschardet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.0.0.tgz", + "integrity": "sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -9747,6 +9765,11 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "encoding-japanese": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", + "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==" + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -10958,6 +10981,11 @@ "argparse": "^2.0.1" } }, + "jschardet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.0.0.tgz", + "integrity": "sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==" + }, "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", diff --git a/package.json b/package.json index d7b70f3f..2702b8b0 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,10 @@ "@oddjs/odd": "^0.37.2", "@tokenizer/http": "^0.6.2", "elm-taskport": "^2.0.1", + "encoding-japanese": "^2.0.0", "fast-text-encoding": "^1.0.6", "file-saver": "^2.0.2", + "jschardet": "^3.0.0", "jszip": "^3.7.1", "load-script2": "^2.0.5", "localforage": "^1.10.0", diff --git a/src/Javascript/processing.ts b/src/Javascript/processing.ts index 108eb89b..60e9f892 100644 --- a/src/Javascript/processing.ts +++ b/src/Javascript/processing.ts @@ -7,9 +7,7 @@ import type { IAudioMetadata } from "music-metadata"; import type { MediaInfo, MediaInfoType } from "mediainfo.js"; -import MediaInfoFactory from "mediainfo.js"; import * as Uint8arrays from "uint8arrays"; - import { transformUrl } from "./urls"; // Contexts @@ -61,14 +59,8 @@ export async function getTags( headUrl: string, getUrl: string, filename: string, - mediainfo: MediaInfo<"object">, + { covers }: { covers: boolean }, ) { - const miResult = await mediainfo - .analyzeData(getSize(headUrl), readChunk(getUrl)) - .catch((_) => null); - const miTags = miResult && pickTagsFromMediaInfo(filename, miResult); - if (miTags) return miTags; - const musicMetadata = await import("music-metadata-browser").then((a) => a.default); const httpTokenizer = await import("@tokenizer/http").then((a) => a.default); @@ -83,10 +75,16 @@ export async function getTags( tokenizer.rangeRequestClient.resolvedUrl = undefined; } - const mmResult = await musicMetadata.parseFromTokenizer(tokenizer); + const mmResult = await musicMetadata.parseFromTokenizer(tokenizer, { skipCovers: !covers }); const mmTags = pickTagsFromMusicMetadata(filename, mmResult); if (mmTags) return mmTags; + const miResult = (await mediaInfoClient()) + .analyzeData(getSize(headUrl), readChunk(getUrl)) + .catch((_) => null); + const miTags = miResult && pickTagsFromMediaInfo(filename, miResult); + if (miTags) return miTags; + return fallbackTags(filename); } @@ -153,10 +151,17 @@ function pickTagsFromMediaInfo(filename: string, result: MediaInfoType): Tags | const tags = result?.media?.track?.filter((t) => t["@type"] === "General")[0]; if (!tags) return null; - let artist = tags.Performer?.length ? tags.Performer : null; - const title = tags.Title?.length ? tags.Title : null; + let artist = typeof tags.Performer == "string" ? tags.Performer : null; + const album = typeof tags.Album == "string" ? tags.Album : null; + + const title = typeof tags.Track == "string" + ? tags.Track + : typeof tags.Title == "string" + ? tags.Title + : null; if (!artist && !title) return null; + if (artist?.includes("�") || album?.includes("�") || title?.includes("�")) return null if (artist && artist.includes(" / ")) { artist = artist @@ -170,7 +175,7 @@ function pickTagsFromMediaInfo(filename: string, result: MediaInfoType): Tags | return { disc: tags.Part_Position || 1, nr: tags.Track_Position || 1, - album: tags.Album && tags.Album.length ? tags.Album : null, + album: album, artist: artist, title: title || filename.replace(/\.\w+$/, ""), genre: tags.Genre || null, @@ -215,9 +220,10 @@ function pickTagsFromMusicMetadata(filename: string, result: IAudioMetadata): Ta // -- async function mediaInfoClient() { + const MediaInfoFactory = await import("mediainfo.js").then(a => a.default) + return await MediaInfoFactory({ coverData: false, - full: true, locateFile: () => { return "../../wasm/media-info.wasm"; }, -- 2.51.2