benrr101 / node-taglib-sharp

A node.js port of mono/taglib-sharp
GNU Lesser General Public License v2.1
34 stars 9 forks source link

Error setting tags for m4a files #103

Open Anogh297 opened 2 months ago

Anogh297 commented 2 months ago

I'm trying to set tags to a m4a file but I keep getting Argument null: ${name} was not provided. It occurs when calling myFile.save()

import { File } from "node-taglib-sharp";
const myFile = File.createFromPath(`${process.cwd()}\\ong_bong_chong.m4a`);

myFile.tag.title = "Ong Bong Chong";
myFile.tag.performers = ["Firoze Jong"];

myFile.save();
myFile.dispose();

this is the error I get

Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\utils.js:53
            throw new Error(`Argument null: ${name} was not provided`);
                  ^

Error: Argument null: text was not provided
    at Guards.notNullOrUndefined (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\utils.js:53:19)
    at ByteVector.fromString (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\byteVector.js:382:24)
    at get data [as data] (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\mpeg4\boxes\isoHandlerBox.js:62:173)
    at Mpeg4BoxRenderer.renderBox (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\mpeg4\mpeg4BoxRenderer.js:33:22)
    at Mpeg4BoxRenderer.renderBox (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\mpeg4\mpeg4BoxRenderer.js:29:45)
    at Mpeg4BoxRenderer.renderBox (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\mpeg4\mpeg4BoxRenderer.js:29:45)
    at Mpeg4File.save (Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp@5.2.3\node_modules\node-taglib-sharp\dist\mpeg4\mpeg4File.js:79:56)
    at file:///Z:/Development/taglib/index.ts:5:8
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)

Node.js v20.9.0

The file is a download from yt-dlp and does not have any tags. ong_bong_chong.zip

subframe7536 commented 2 months ago

hot fix: https://github.com/subframe7536/node-taglib-sharp-memory/commit/04188810e92de0fdbf77243e058f8b9309654273

Anogh297 commented 2 months ago

Thank you for your reply. Installing your version of it throws another error. Would appreciate if you could tell me what I would need to do to fix this

import taglib from "node-taglib-sharp-extend";
const { File } = taglib;

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in Z:\Development\taglib\node_modules\node-taglib-sharp-extend\package.json imported from Z:\Development\taglib\index.js      
    at new NodeError (node:internal/errors:406:5)
    at exportsNotFound (node:internal/modules/esm/resolve:268:10)
    at packageExportsResolve (node:internal/modules/esm/resolve:542:13)
    at packageResolve (node:internal/modules/esm/resolve:772:14)
    at moduleResolve (node:internal/modules/esm/resolve:838:20)
    at defaultResolve (node:internal/modules/esm/resolve:1043:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:383:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:352:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:228:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

Node.js v20.9.0```
subframe7536 commented 2 months ago

Please try

import { File } from "node-taglib-sharp-extend";
Anogh297 commented 2 months ago

Same error.

subframe7536 commented 2 months ago

Fixed in v0.2.7

Anogh297 commented 2 months ago
Z:\Development\taglib>node index   
node:internal/errors:497
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp-extend@0.2.7_magic-string@0.30.8\node_modules\node-taglib-sharp-extend\dist\taglib\byteVector' imported from Z:\Development\taglib\node_modules\.pnpm\node-taglib-sharp-extend@0.2.7_magic-string@0.30.8\node_modules\node-taglib-sharp-extend\dist\taglib\index.js
    at new NodeError (node:internal/errors:406:5)
    at finalizeResolution (node:internal/modules/esm/resolve:233:11)
    at moduleResolve (node:internal/modules/esm/resolve:845:10)
    at defaultResolve (node:internal/modules/esm/resolve:1043:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:383:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:352:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:228:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
    at link (node:internal/modules/esm/module_job:84:36) {
  url: 'file:///Z:/Development/taglib/node_modules/.pnpm/node-taglib-sharp-extend@0.2.7_magic-string@0.30.8/node_modules/node-taglib-sharp-extend/dist/taglib/byteVector',
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v20.9.0
subframe7536 commented 2 months ago

Sorry, this package only support modern bundlers.

You can try esno

edit: after some works, everything should be OK in v0.2.8

Anogh297 commented 2 months ago

Thank you, it works as expected. However typescript still throws this error Property 'File' does not exist on type 'typeof import("Z:/Development/taglib/node_modules/.pnpm/node-taglib-sharp-extend@0.2.8_magic-string@0.30.8/node_modules/node-taglib-sharp-extend/dist/index", { with: { "resolution-mode": "import" } })'.

import * as taglib from "node-taglib-sharp-extend";
const { File } = taglib; 
subframe7536 commented 2 months ago

Sorry I have no idea with that. The type resolution have no error according to this site

Anogh297 commented 2 months ago

I see. Perhaps typescript is not emitting the declaration files properly? The index.d.ts file is just export * from 'node-taglib-sharp-memory/src';

image

subframe7536 commented 2 months ago

I found that you are right, I used the function under utils when processing files myself, and did not find the default import error. And the above inspection website also found no errors, so it was published. I think I need to export types a different way.

subframe7536 commented 2 months ago

finally... v0.2.9

Anogh297 commented 2 months ago

Thanks a lot! It's working fine and the intellisense works too:D Sorry to be a bother but I had a last question, when trying to add the tags the file gets corrupted. I don't think it's the library's fault but rather yt-dlp where I am getting my file from. Since the library works fine and I am only getting this issue with recently downloaded files. Can you suggest me a way of fixing it?


// myFile.corruptionReasons
[
  'Box header specified a size of 805306368 bytes but only 3478550 bytes left in the file'
]
subframe7536 commented 2 months ago

sure, please provide a minimal reproduction and source audio file

Anogh297 commented 2 months ago

yt-dlp executable yt-dlp https://www.youtube.com/watch?v=2SUwOgmvzK4 -f m4a

audio.zip

subframe7536 commented 2 months ago

This seems to be an existing issue in C# implemention: https://github.com/mono/taglib-sharp/issues/306

@benrr101 @digimezzo any idea?

benrr101 commented 1 month ago

Sorry I haven't been able to look at this project in quite a while. I'm wrapping up another project and hope to continue with this one relatively soon-ish :tm:

stuartambient commented 1 month ago

Sorry I haven't been able to look at this project in quite a while. I'm wrapping up another project and hope to continue with this one relatively soon-ish ™️

I did some testing earlier on, got diverted somewhere else but back now on my music project. I've been setting up various tables and pages for metadata editing but wanted to ask if you feel, in particular the unified approach is stable ? I'm not doing video at this point and even my supported codecs are limited to mp3, flac, m4a, and ape.

benrr101 commented 3 weeks ago

@stuartambient I think the idea of taglib (sharp or otherwise) was always to provide a unified abstraction but also provide interfaces for interacting with specific tagging formats in an advanced manner. The unified abstraction is the most documented in the wiki for this project, and I think for a lot of users this enough. Using the advanced interfaces requires some working knowledge of the tagging formats, otherwise metadata can get messed up. I mean to write more documentation on how it all works, but it'll take me time I don't have at the moment 😓

What are your thoughts?

stuartambient commented 2 weeks ago

I'm settled in my current strategy to use the unified approach. I have no idea what I might need more advanced methods for at this point but if things change I'll learn. My current dilemma is that in my app, I've been using Borewit/Music-metadata, maybe you're familiar with it. It's node based and only reads and parses metadata. It presents different groups of metadata, 'format', 'common', 'trackInfo' and 'native'. I mostly pull from common and format.

There are some fields from music-metadata and node-taglib-sharp that conflict in data structure, i.e. artist (string) vs performers (array). I'm considering do I write some code that after taglib writes, music-metadata can parse or do I use taglib for both. Node-taglib-sharp seems like it could easily replace my use of the aforementioned but I know little about standards and am concerned about other music software being able to read the metadata, like VLC, Foobar, Musicbee, etc.

I realize that I'll need to do testing on my own.

tldr - are the metadata data structures used in node-taglib-sharp compatible with other music players / managers. Is there a standard that all or most music software shares about metadata ?

benrr101 commented 2 weeks ago

Ah, I see what you're saying. To answer your ultimate question, yes the tags that node-taglib-sharp stores are compatible with your favorite music software. I test things I'm unsure about against foobar2000 and vlc to make sure they behave as expected. For your specific example of artist/performers, most (if not all, I can't remember fully right now) are stored as a single tag with a delimitor between values in the array. If only only need one artist, you're always welcome to read/write a single value array, or interact with it using the First* properties.

To get more into the weeds, it does depend a lot on the tagging format that is used. For example, ASF has a single field for artist that's baked into the format. While FLAC is basically a fancy list of key/value pairs, so it's possible to store multiple key/value pairs with the same key (eg, split an array of artists over multiple pairs). Although there is precedent for the most popular tagging fields, ultimately, the tagging formats are open-ended enough that you can store tags however you want. Eg, iTunes is notorious for inventing its own fields or using tags in uncommon ways. This is why the advanced mechanisms exist - even if we can cover all "most common behavior" with configuration, having an escape hatch to do things manually is beneficial to some users.

Also, here's a wiki page I found recently for where Foobar2000 pulls its tags from. https://wiki.hydrogenaud.io/?title=Tag_Mapping

stuartambient commented 2 weeks ago

@benrr101 thank you for the reply and explanation. Very helpful and the itunes example gives me a better perspective.

subframe7536 commented 2 weeks ago

@stuartambient I made a new package music-metadata-wasm recently, which use lofty-rs and build by wasm-pack, can also read / write the tag. Would you like to have a try?

stuartambient commented 2 weeks ago

@subframe7536 maybe at some point. Is it fork from Borewit ?

subframe7536 commented 2 weeks ago

@stuartambient Noop, a brand new one. At lease the m4a file tag could be correctly written. Maybe have better performance

stuartambient commented 1 week ago

@stuartambient Noop, a brand new one. At lease the m4a file tag could be correctly written. Maybe have better performance

I'm not supporting m4a right now. The player uses html audio and doesn't always handle m4a well. I'll have to look at it in the future. Seems like a popular format.