polyfloyd / rust-id3

A rust library for reading and writing ID3 metadata
MIT License
240 stars 46 forks source link

Allow operating on mp3 files in-memory #117

Closed DCNick3 closed 10 months ago

DCNick3 commented 10 months ago

For some use-cases it might be better to operate purely in-memory, without having an actual mp3 file.

However, write_to_path, which seems to be the correct way to apply tags to an existing mp3 file, requires you to have a file to operate. It would be nice to have something that would operate on T: io::Read + io::Write + io::Seek or just a Cursor<T>

polyfloyd commented 10 months ago

The underlying storage abstraction does support in-memory buffers. I'll see how this can be nicely exposed :)

Thank you for the suggestion!

polyfloyd commented 10 months ago

I have pushed possible implementation in the expose-storage-file branch. Could you please check whether this does what you expect it to do?

DCNick3 commented 10 months ago

Yep, it seems to work for me!

However there are some other APIs that do still can't operate in-memory:

Specifically, I was using id3::v1v2::write_to_path to not only set the id3v2 tag, but also to remove the v1 tag. Internally it uses id3::v1::Tag::remove, which doesn't seem to use the FileStorage trait and operates on File directly..

Then there are all the id3::Tag::write_to_* APIs, but they seem to be already covered by the Encoder. Is there any difference between those APIs?

skabber commented 10 months ago

I don't know if this helps but I was able to get around this by using a Cursor

use std::io::Cursor;

let curs = Cursor::new(&mut bytes_of_mp3);

// tag is an id3::tag::Tag
tag.write_to(curs, Version::Id3v23).unwrap();

// you can then get the bytes and do what you like with them
let bytes = b.as_slice();
polyfloyd commented 10 months ago

@skabber That works to get the raw ID3 tag, but write_to does not take into account any existing data. So if the newly written tag is larger than any existing tag, the data coming after will be partially overwritten!

write_to_path is aware of the size the tag and trailing data and does not have this problem. But this API does currently not permit writing to in-memory buffers, which is what this issue is about :)

polyfloyd commented 10 months ago

@DCNick3 I have updated the patch to introduce a write_to_file family of functions everywhere. Please check again

skabber commented 10 months ago

@skabber That works to get the raw ID3 tag, but write_to does not take into account any existing data. So if the newly written tag is larger than any existing tag, the data coming after will be partially overwritten!

write_to_path is aware of the size the tag and trailing data and does not have this problem. But this API does currently not permit writing to in-memory buffers, which is what this issue is about :)

Thank you. You may have just exposed a bug in my project :)

DCNick3 commented 10 months ago

@polyfloyd

@DCNick3 I have updated the patch to introduce a write_to_file family of functions everywhere. Please check again

Yep, this seems to work nicely!

polyfloyd commented 10 months ago

Good! I will be releasing this in v1.10 then