Try upgrading to music-metadata from music-metadata-browser

This commit is contained in:
Jordan Eldredge 2025-07-04 10:06:13 -07:00
parent 366e79525e
commit e043a1b5b8
8 changed files with 134 additions and 22 deletions

View file

@ -6,6 +6,7 @@
### Improvements
- Switched id3/metadata parsing from using a very old version of `music-metadata-browser` to the latest version of `music-metadata`. `music-metadata-browser` is still supported for users of `webamp/lazy` for backwards compatibility, but it is no longer the default.
- Added new `Webamp` instance methods:
- `webamp.toggleShuffle`
- `webamp.toggleRepeat`
@ -15,6 +16,7 @@
### Bug Fixes
- Fixed broken ID3 tag and bitrate parsing.
- Fix bug where scrolling the main window or playlist window would change the volume but also (incorrectly) scroll the page.
- Fix bug where resizing the window such that the current layout cannot fit on the page, while also scrolled down the page, would cause the layout to be recentered out of view.
- Avoid a console log from Redux Dev Tools.

View file

@ -128,9 +128,7 @@ export async function getWebampConfig(
// @ts-ignore
import(/* webpackChunkName: "jszip" */ "jszip/dist/jszip"),
requireMusicMetadata: () =>
import(
/* webpackChunkName: "music-metadata-browser" */ "music-metadata-browser/dist/index"
),
import(/* webpackChunkName: "music-metadata" */ "music-metadata"),
__initialState: screenshot ? screenshotInitialState : initialState,
__butterchurnOptions,
__customMiddlewares: [sentryMiddleware, loggerMiddleware],

View file

@ -1,13 +1,13 @@
import invariant from "invariant";
import { IMusicMetadataBrowserApi } from "./types";
import { IMusicMetadataApi, IMusicMetadataBrowserApi } from "./types";
import { IAudioMetadata } from "music-metadata-browser"; // Import music-metadata type definitions
import * as Utils from "./utils";
type MediaDataType = string | ArrayBuffer | Blob;
export function genMediaTags(
export async function genMediaTags(
file: MediaDataType,
musicMetadata: IMusicMetadataBrowserApi
musicMetadata: IMusicMetadataBrowserApi | IMusicMetadataApi
): Promise<IAudioMetadata> {
invariant(
file != null,
@ -20,7 +20,29 @@ export function genMediaTags(
};
if (typeof file === "string") {
return musicMetadata.fetchFromUrl(file, options);
if (
"parseWebStream" in musicMetadata &&
typeof musicMetadata.parseWebStream === "function"
) {
const response = await fetch(file);
if (!response.ok) {
throw new Error(
`Failed to fetch URL: ${file}, status: ${response.status}`
);
}
const webStream = response.body;
if (webStream == null) {
throw new Error("Response body is null, cannot parse metadata.");
}
return musicMetadata.parseWebStream(webStream, undefined, options);
}
if (
"fetchFromUrl" in musicMetadata &&
typeof musicMetadata.fetchFromUrl === "function"
) {
return musicMetadata.fetchFromUrl(file, options);
}
throw new Error("No suitable method available to parse URL");
}
// Assume Blob
return musicMetadata.parseBlob(file as Blob, options);

View file

@ -1,3 +1,4 @@
import type { AnyWebByteStream, IFileInfo } from "strtok3";
import { PlaylistState } from "./reducers/playlist";
import { SettingsState } from "./reducers/settings";
import { UserInputState } from "./reducers/userInput";
@ -864,19 +865,32 @@ export interface IMusicMetadataBrowserApi {
audioTrackUrl: string,
options?: IOptions
): Promise<IAudioMetadata>;
}
/**
* Type definition of the portion of the music-metadata module we use in Webamp.
*/
export interface IMusicMetadataApi {
/**
* Parse audio from Node Stream.Readable
* @param stream - Stream to read the audio track from
* @param fileInfo - File information object or MIME-type, e.g.: 'audio/mpeg'
* @param options - Parsing options
* @returns Metadata
*/
parseWebStream(
webStream: AnyWebByteStream,
fileInfo?: IFileInfo | string,
options?: IOptions
): Promise<IAudioMetadata>;
/**
* Parse audio from Node Buffer
* @param {Stream.Readable} stream Audio input stream
* @param {string} mimeType <string> Content specification MIME-type, e.g.: 'audio/mpeg'
* Parse Web API File
* @param {Blob} blob
* @param {IOptions} options Parsing options
* @returns {Promise<IAudioMetadata>}
*/
parseBuffer(
buf: Buffer,
mimeType?: string,
options?: IOptions
): Promise<IAudioMetadata>;
parseBlob(blob: Blob, options?: IOptions): Promise<IAudioMetadata>;
}
export interface Extras {

View file

@ -1,5 +1,5 @@
import JSZip from "jszip";
import * as musicMetadataBrowser from "music-metadata-browser";
import * as musicMetadata from "music-metadata";
import { Options } from "./types";
import WebampLazy, { PrivateOptions } from "./webampLazy";
@ -28,7 +28,7 @@ export default class Webamp extends WebampLazy {
super({
...options,
requireJSZip: async () => JSZip,
requireMusicMetadata: async () => musicMetadataBrowser,
requireMusicMetadata: async () => musicMetadata,
});
}
}

View file

@ -51,8 +51,8 @@ export interface PrivateOptions {
}
export interface InjectableDependencies {
requireJSZip: () => Promise<any>; // TODO: Type JSZip
requireMusicMetadata: () => Promise<any>; // TODO: Type music-metadata-browser
requireJSZip: () => Promise<typeof import("jszip")>;
requireMusicMetadata: () => Promise<typeof import("music-metadata")>;
}
class Webamp {

View file

@ -134,6 +134,7 @@
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"milkdrop-preset-converter-aws": "^0.1.6",
"music-metadata": "^11.6.0",
"music-metadata-browser": "^0.6.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",

View file

@ -5779,6 +5779,20 @@
dependencies:
defer-to-connect "^2.0.1"
"@tokenizer/inflate@^0.2.7":
version "0.2.7"
resolved "https://registry.yarnpkg.com/@tokenizer/inflate/-/inflate-0.2.7.tgz#32dd9dfc9abe457c89b3d9b760fc0690c85a103b"
integrity sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==
dependencies:
debug "^4.4.0"
fflate "^0.8.2"
token-types "^6.0.0"
"@tokenizer/token@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz"
@ -9344,7 +9358,7 @@ content-disposition@0.5.4, content-disposition@^0.5.2:
dependencies:
safe-buffer "5.2.1"
content-type@~1.0.4, content-type@~1.0.5:
content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
@ -9999,6 +10013,13 @@ debug@^3.2.7:
dependencies:
ms "^2.1.1"
debug@^4.4.0, debug@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
dependencies:
ms "^2.1.3"
debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz"
@ -12239,6 +12260,11 @@ fflate@^0.7.3:
resolved "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz"
integrity sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==
fflate@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea"
integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
figures@^1.3.5:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
@ -12304,6 +12330,16 @@ file-type@^12.0.0:
resolved "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz"
integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==
file-type@^21.0.0:
version "21.0.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-21.0.0.tgz#b6c5990064bc4b704f8e5c9b6010c59064d268bc"
integrity sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==
dependencies:
"@tokenizer/inflate" "^0.2.7"
strtok3 "^10.2.2"
token-types "^6.0.0"
uint8array-extras "^1.4.0"
file-type@^3.8.0:
version "3.9.0"
resolved "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz"
@ -14045,7 +14081,7 @@ ieee754@1.1.13:
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz"
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
ieee754@^1.1.13, ieee754@^1.1.4:
ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@ -17606,6 +17642,11 @@ media-typer@0.3.0:
resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
media-typer@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561"
integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==
memfs@^3.4.3:
version "3.6.0"
resolved "https://registry.npmjs.org/memfs/-/memfs-3.6.0.tgz"
@ -18648,7 +18689,7 @@ ms@2.1.2:
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@ -18702,6 +18743,20 @@ music-metadata-browser@^0.6.1:
remove "^0.1.5"
typedarray-to-buffer "^3.1.5"
music-metadata@^11.6.0:
version "11.6.0"
resolved "https://registry.yarnpkg.com/music-metadata/-/music-metadata-11.6.0.tgz#edc6c136c9ada31ee7ce9ed0c7a7c47546e9a54b"
integrity sha512-l7MbWpuGM5GK8gol22L9tou8d/IoFyS8dnsfLbO6cocjlyMwgyLaCIqdwhp4sN1Nzz/Ql/K9kRLvRJDCVKjO3g==
dependencies:
"@tokenizer/token" "^0.3.0"
content-type "^1.0.5"
debug "^4.4.1"
file-type "^21.0.0"
media-typer "^1.1.0"
strtok3 "^10.3.1"
token-types "^6.0.3"
uint8array-extras "^1.4.0"
music-metadata@^3.4.0:
version "3.8.0"
resolved "https://registry.npmjs.org/music-metadata/-/music-metadata-3.8.0.tgz"
@ -23846,6 +23901,13 @@ strnum@^1.0.5:
resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz"
integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==
strtok3@^10.2.2, strtok3@^10.3.1:
version "10.3.1"
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-10.3.1.tgz#80fe431a4ee652de4e33f14e11e15fd5170a627d"
integrity sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw==
dependencies:
"@tokenizer/token" "^0.3.0"
strtok3@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/strtok3/-/strtok3-2.3.0.tgz"
@ -24340,6 +24402,14 @@ token-types@^1.0.1:
dependencies:
ieee754 "^1.1.13"
token-types@^6.0.0, token-types@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/token-types/-/token-types-6.0.3.tgz#684f4f40e0750078ec644c826207a2c160b827a8"
integrity sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ==
dependencies:
"@tokenizer/token" "^0.3.0"
ieee754 "^1.2.1"
toml@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz"
@ -24728,6 +24798,11 @@ ufo@^1.3.2:
resolved "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz"
integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==
uint8array-extras@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/uint8array-extras/-/uint8array-extras-1.4.0.tgz#e42a678a6dd335ec2d21661333ed42f44ae7cc74"
integrity sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==
unbox-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz"