MP3 ID3 Read Cover Art: Can only read embedded - c#

I've tried every Library i could find, and been searching StackOverflow and google for days without getting it working.
Libraries: UltraID3Lib, TagLib, IdSharp, ID3 Tag Library by Perry Butler, ID3Lib, C# ID3 Library, ID3.Net, ... ...
None of these seem to be able to get the Cover Art that winamp shows the file has. There is no cover art or jpg or anything of the sort in the folder containing the mp3 either.
Only embedded Cover Art is showing up in every library, but other are not.
When opening winamp mp3 "File Info", if the "origin" displays "embedded" it shows up in every library, but if it shows origin "folder" then only winamp seems to know about it. Mind you, there are no images in any folder at all, the mp3 itself does contain this image.
So far i only found 1 other compiled application that gets these images, but i have no way of finding out how they did it.
Anyone know what I'm doing wrong? (I am using TagLib atm: https://github.com/mono/taglib-sharp)
public Song(string filePath)
{
var id3 = TagLib.File.Create(filePath);
TrackNumber = (Winamp.PlaylistPosition + 1);
Artist = id3.Tag.FirstArtist;
Title = id3.Tag.Title;
Position = Winamp.GetTrackPosition();
Length = Winamp.GetTrackLength();
AlbumArt = LoadPicture(id3);
Status = Winamp.GetPlaybackStatus();
}
private Bitmap LoadPicture(TagLib.File file)
{
Image currentImage = null;
if (file.Tag.Pictures.Length > 0)
{
TagLib.IPicture pic = file.Tag.Pictures[0];
MemoryStream ms = new MemoryStream(pic.Data.Data);
if (ms.Length > 0)
currentImage = Image.FromStream(ms);
ms.Close();
}
return (Bitmap)currentImage;
}

Related

Get Music files details only

Basically I am trying to get the details of a music file inside an android device (Ex. The music's title, artist, etc) and store them to a list<>. (SongData contains the list, and it contains a list of Song object.)
public void PopulateSongList(Context context) {
SongData songData = new SongData();
Android.Net.Uri musicUri = Android.Provider.MediaStore.Audio.Media.ExternalContentUri;
//Used to query the media files.
ICursor musicCursor = context.ContentResolver.Query(musicUri, null, null, null, null);
if (musicCursor != null && musicCursor.MoveToFirst())
{
int songID = 0;
//get columns.
int songTitleColumn = musicCursor.GetColumnIndex("title");
int songArtistColumn = musicCursor.GetColumnIndex("artist");
//add songs to list
do
{
String songTitle = musicCursor.GetString(songTitleColumn);
//Tried, but file name does not contain file extension.
if (songTitle.ToLower().Contains(".mp4") || songTitle.ToLower().Contains(".m4a"))
{
String songArtist = musicCursor.GetString(songArtistColumn);
songData.AddNewSong(new Song(++songID, songTitle, songArtist, null));
}
}
while (musicCursor.MoveToNext());
}
}
The code works well but however in the do..while loop, songTitle also contains other files that are not music files as well.
I tried checking for file extensions but it does not work, and after using the debugger again, the file name given does not contain the file extension.
So how do I make sure that it only grabs details from a music file, and not other kind of files?
(Also, I want to grab the name of the artist of a music file, but apparently int songArtistColumn = musicCursor.GetColumnIndex("artist"); does not seem to work.)
Finally, how do I get the image of a music file? (The song image).
You can try to use musicCursor.GetColumnNames() to see what the file is allowing you to work with.
Here's an image of the possible results you can get if you execute it.
musicCursor.GetColumnNames() will return the results in a string[] so you can use List<string> songInfo = new List<string>(string[]);
A problem you might get is a NullException, this happens when the data you're trying to work with have a value of null. You'll get this value directly from the file if the Artist or other values are unknown.
I don't know where the Image file is stored, but if it's stored with the music file it will most likely be stored in a byte[]. So you'll need to convert the byte[] to an image.

Get Albumart in .mp3 file for Windows Store App

How can i get the AlbumArt image in the mp3 file? I am developing Windows Store app with c#.
MusicProperties class gives me Album name artist name vs. But it cant give me albumart.
Check out MSDN sample to show thumbnail of any file. It also consists how to retrieve the album art.
File and folder thumbnail sample
If you want to save the album art check out How to store save Thumbnail image in device in windows 8 metro apps c#
UPDATE 1
MediaFile is StorageFile. ImageControl is <Image ... />
using (StorageItemThumbnail thumbnail = await MediaFile.GetThumbnailAsync(ThumbnailMode.MusicView, 300))
{
if (thumbnail != null && thumbnail.Type == ThumbnailType.Image)
{
var bitmapImage = new BitmapImage();
bitmapImage.SetSource(thumbnail);
ImageControl.Source = bitmapImage;
}
}
here's my quick and short solution for that problem thirding TagLib#: (http://taglib.github.io/)
using TagLib;
var file = TagLib.File.Create(filename);
var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
imageBox.Image = Image.FromStream(new MemoryStream(bin));
I found a solution here How to: Get IDE Tags and Thumbnails of a file
var bitmapImage = new BitmapImage();
//Get Album cover
using (StorageItemThumbnail thumbnail = await file.GetThumbnailAsync(ThumbnailMode.MusicView, 300))
{
if (thumbnail != null && thumbnail.Type == ThumbnailType.Image)
{
bitmapImage.SetSource(thumbnail);
}
else
{
//Error Message here
}
}

Embed Album Art in Mp3 using Tag Lib C#

Trying to add Album art using c# tag lib,
TagLib.File trackFile = TagLib.File.Create(strLocalFile);
Picture picture = new Picture("Picture path");
picture.Type = PictureType.FrontCover;
picture.MimeType = "image/jpeg";
picture.Description = "Front Cover";
trackFile.Tag.Pictures = new IPicture[1] { picture };
trackFile.Save();
I get picture in windows media player, itunes and iphone (only in portrait mode). When i switch to landscape mode, album art is displayed but when slide across the cover flow album art disappears.
Am i missing something in code ?
I use iTunes 11, iOS 6 on iPhone 4s
Let me cite myself:
I found that iTunes hates UTF-16 and that's what's the problem there.
targetMp3File = TagLib.File.Create(...);
// define picture
TagLib.Id3v2.AttachedPictureFrame pic = new TagLib.Id3v2.AttachedPictureFrame();
pic.TextEncoding = TagLib.StringType.Latin1;
pic.MimeType = System.Net.Mime.MediaTypeNames.Image.Jpeg;
pic.Type = TagLib.PictureType.FrontCover;
pic.Data = TagLib.ByteVector.FromPath(...);
// save picture to file
targetMp3File.Tag.Pictures = new TagLib.IPicture[1] { pic };
targetMp3File.Save();
So essentially the whole thing is in the pic.TextEncoding line. Additionally i assigned the Mime Type through the .NET constant.
Source: Having trouble writing ArtWork with Taglib-sharp 2.0.4.0 in .Net
This should work for both iTunes and iPod/iPad/iPhone. BUT this works only for MP3 files...

C# mp3 ID tags with taglib - album art

Im making my own mp3 tagger, and everything is fine so far. Although im stuck reading the album art tag.
I would like to know how to display the cover in a C#.NET picture box, but everything iv seen about that particular tag is confusing me.
I know i can get tags from files like this
txtAlbum.Text = currentFile.Tag.Album;
but all i need to do is grab the picture from the file and whack it in a picturebox. Then i would like to know how to write a picture (jpg, png) into the file and overwrite the existing one.
Any help would be greatly appreciated, and thank you for your valued time.
Try this
TagLib.File tagFile = TagLib.File.Create(path);
IPicture newArt = new Picture(tmpImg);
tagFile.Tag.Pictures = new IPicture[1] {newArt};
tagFile.Save();
EDIT
var file = TagLib.File.Create(filename);
if (file.Tag.Pictures.Length >= 1)
{
var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
PreviewPictureBox.Image = Image.FromStream(new MemoryStream(bin)).GetThumbnailImage(100, 100, null, IntPtr.Zero);
}
here's my quick and short solution for that problem:
var file = TagLib.File.Create(filename);
var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
imageBox.Image = Image.FromStream(new MemoryStream(bin));

Trouble playing mp3s after id3 image edit

Due to hardware restrictions, the software we produce tries to ensure that any audio file it imports into it's library (ready to be copied onto the hardware) is an acceptable bit rate.
Recently we've started using FFmpeg to convert a number of different audio types to mp3 to allow them to be imported and used on our hardware. Whilst the conversion works fine and the mp3 files work on our hardware afterwards, we're having issues specifically when adding an album art to the ID3 tags of the mp3. The track will not play audio in our software. It also seems that Windows cannot pick up the values of the ID3 tags in explorer, but Windows Media Player will still play the track.
This problem only seems to occur when changing a newly converted mp3s' ID3 tags after using FFmpeg. Changing tags on mp3s from other sources or those that have already got ID3 tag album art is fine.
The code for using FFmpeg from our software is as follows:
private const string SAMPLE_RATE = "44100";
...
//create temp file for output
outFile = Path.GetTempFileName();
outFile = Path.ChangeExtension(outFile, "mp3");
if (!File.Exists(inFile))
return false;
string metadata = (inFile.EndsWith("mp3")) ? " " : " -map_meta_data 0:0 ";
//build process
string workingDirectory = Environment.CurrentDirectory;
ProcessStartInfo FFmpegProcessInfo = new ProcessStartInfo();
FFmpegProcessInfo.WorkingDirectory = workingDirectory;
FFmpegProcessInfo.FileName = "ffmpeg.exe";
FFmpegProcessInfo.Arguments = "-i \"" + inFile + "\"" + " -ar "+SAMPLE_RATE + metadata + "\"" + outFile + "\""; //default conversion to SAMPLE_RATE
FFmpegProcessInfo.CreateNoWindow = true; //hide from user
//let us grab the output
FFmpegProcessInfo.RedirectStandardError = true;
FFmpegProcessInfo.RedirectStandardOutput = true;
FFmpegProcessInfo.UseShellExecute = false;
Process p = Process.Start(FFmpegProcessInfo);
To change the ID3 tags we have started using TagLib-Sharp and the code for changing the ID3 tags is:
public void SetId3Tags(string path, Bitmap image, IDictionary<string, string> values)
{
FileInfo fileInfo = new FileInfo(path);
fileInfo.Attributes = FileAttributes.Normal;
try
{
TagLib.File tagFile = TagLib.File.Create(path);
if (values.ContainsKey("Title"))
tagFile.Tag.Title = values["Title"];
if (values.ContainsKey("Artist"))
tagFile.Tag.Performers = new string[1] { values["Artist"] };
if (values.ContainsKey("Comments"))
tagFile.Tag.Comment = values["Comments"];
if (image != null) {
string tmpImg = Path.GetTempFileName();
image.Save(tmpImg);
IPicture newArt = new Picture(tmpImg);
tagFile.Tag.Pictures = new IPicture[1] {newArt};
}
tagFile.Save();
}
catch (Exception e)
{
_logger.Log(e);
}
}
And the code used to play the track in the software (FilgraphManager in QuartzTypeLib):
public void Play()
{
if (!_isPaused)
{
_graphManager = new FilgraphManager();
_mp3control = (IMediaControl)_graphManager;
_mp3position = (IMediaPosition)_graphManager;
_tempFile = Path.GetTempFileName();
File.Copy(_fullPath, _tempFile, true);
_mp3control.RenderFile(_tempFile);
}
else
{
_isPaused = false;
}
_mp3control.Run();
}
And the error when executing _mp3control.RenderFile(_tempFile):
{System.Runtime.InteropServices.ExternalException} = {"Exception from HRESULT: 0x80040266"}
at QuartzTypeLib.FilgraphManagerClass.RenderFile(String strFilename)
My largest problem here is that I don't know whether the fault lies with (our implementation of) FFmpeg (large library that's used fine in many other places), TagLib-Sharp or the audio playing.
Edit 1: Following J. Andrew Laughlin's advice I've been looking at the differences of the ID3 tags in the hex of each file. This is what I've found:
The initial input is ID3v2.3. After re-encoding with FFmpeg, the ID3 data is v2.4. This initial re-encoded file plays fine in media players and our software. Using TagLib# in our software to add album art keeps ID3v2.4 but the tags are only available using TagLib# to read them and it only plays in media players such as Windows Media Player. Using another tool to change the ID3 tags (in this case AudioShell Tag Editor) and add the same album art changed the ID3 version to 2.3 and meant that the mp3 played on our softwares audio player as well as other media players - However changing the tags afterwards produces an exception when saving the image.
One other thing I tried was to rip out the ID3v2.4 block completely after the re-encoding, this plays (as you'd expect) in all media players. When using the TagLib# on this untagged file, the tags were correctly applied (v2.3) and it continued to play properly in our software as well as others.
Unless anyone can suggest an elegant solution (either force TagLib# to write a new ID3v2.3 block or stop FFmpeg from writing one at all) I think I may just programmatically remove the ID3v2.4 block from the file after encoding and then write a new one.
TagLib# can be used to "downgrade" an ID3 tag from 2.4 to 2.3. I personally prefer to convert my ID3 tags to 2.3 since it is more consistently adopted across music players.
It's been a while, but I believe you can use the following in your above code:
TagLib.Id3v2.Tag id3v2tag = tagFile.GetTag(TagLib.TagTypes.Id3v2, false);
if(id3v2tag != null)
id3v2tag.Version = 3;
tagFile.Save();
Alternatively, you can force all tags to render in 2.3 by using the following code when your application initializes:
TagLib.Id3v2.Tag.DefaultVersion = 3;
TagLib.Id3v2.Tag.ForceDefaultVersion = true;
TagLib# can also remove tags completely and re-add them, but it shouldn't have to come to that.
Good luck!

Categories

Resources