antoninastefanowska / expo-music-info

Expo-compatible React Native audio metadata extractor.
MIT License
9 stars 1 forks source link

How to use Album Art in Image Component? #4

Closed kartikeyvaish closed 3 years ago

kartikeyvaish commented 3 years ago

I want to render the Album art of the .mp3** file but the URI is Base64 Encoded How can we use that Picture uri in Image Component??

const [CoverImage, SetCoverImage] = useState("");

let metadata = await MusicInfo.getMusicInfoAsync(
  "file:///storage/sdcard1/Music/We Are Legend.mp3",
  {
    title: true,
    artist: true,
    album: true,
    genre: true,
    picture: true,
  }
);

SetCoverImage(metadata.picture);
console.log(metadata.picture);    // This logs "data:image/jpeg;base64,AP/Y/+AAEEpGSUYAAQEAAAEAAQAA/9sAhAADAgIKCgoKCgoKCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCAgICAoKCggICw0KCA0ICAoIAQMEBAYFBgoGBgoPDQoNDw0PDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND...(truncated to the first 10000 characters)

In render Part I've written this

{CoverImage === "" ? null : (
      <Image
        source={{ uri: CoverImage }}
        style={{ height: 200, width: 250 }}
      />
  )}

But it Gives me this error - error while updating property 'src' of a view managed by RCTImageView

antoninastefanowska commented 3 years ago

metadata.picture is an object with two fields: description and pictureData. Image data is contained in metadata.picture.pictureData.

So, in your case, if I'm not mistaken, the correct way to do this would be:

{CoverImage === "" ? null : ( <Image source={{ uri: CoverImage.pictureData }} style={{ height: 200, width: 250 }} /> )}

You can freely use Base64 encoded images as a source in Image components. It's just that metadata.picture is an object with a string field instead of a direct string that's required for the source uri.

kartikeyvaish commented 3 years ago
const [CoverImage, SetCoverImage] = useState(null);

let metadata = await MusicInfo.getMusicInfoAsync(
  "file:///storage/sdcard1/Music/We Are Legend.mp3",
  {
    title: true,
    artist: true,
    album: true,
    genre: true,
    picture: true,
  }
);
SetCoverImage(metadata.picture.pictureData);

In render Part -->

{CoverImage === null ? null : (
    <>
      <Button title="Press"></Button>
      <Image
        source={{ uri: CoverImage }}
        style={{ height: 200, width: 250 }}
      />
    </>
  )}

Just to verify the CoverImage state is being updated I added a Button..So Now the button shows up but not the Image Component

kartikeyvaish commented 3 years ago

This is the whole code

import React, { useEffect, useState } from "react";
import { View, StyleSheet, Image, Button } from "react-native";
import MusicInfo from "expo-music-info";

function HomeScreen(props) {
  const [CoverImage, SetCoverImage] = useState(null);

  useEffect(() => {
    GetFiles();
  }, []);

  const GetFiles = async () => {
    let metadata = await MusicInfo.getMusicInfoAsync(
      "file:///storage/sdcard1/Music/We%20Are%20Legend.mp3",
      {
        title: true,
        artist: true,
        album: true,
        genre: true,
        picture: true,
      }
    );
    SetCoverImage(metadata.picture.pictureData);
  };

  return (
    <View style={styles.container}>
      {CoverImage === null ? null : (
        <>
          <Button title="Press"></Button>
          <Image
            style={{
              width: 100,
              height: 50,
              resizeMode: "contain",
              borderWidth: 1,
              borderColor: "red",
            }}
            source={{ uri: CoverImage }}
          />
        </>
      )}
    </View>
  );
}

export default HomeScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "white",
    paddingTop: 50,
    padding: 20,
  },
});
kartikeyvaish commented 3 years ago

on Executing this command console.log(metadata.picture.pictureData); I get this error

PayloadTooLargeError: request entity too large
antoninastefanowska commented 3 years ago

Hmm, I tested your code on my device and it works fine.

I suppose that in the case of this specific file, there is a problem with the album cover image. Like the error said - it might be too large for react native. I'm not sure if I can help with this one, maybe compression could make it possible (for example https://docs.expo.io/versions/latest/sdk/imagemanipulator/), but unfortunately I haven't tried it myself.

For now I suggest you try with different music file.

kartikeyvaish commented 3 years ago

Yes it worked for a different Music File. But what's the reason behind this??

Any other Solution other than Expo Image Manipulator. I am designing a Music Player for which I needed the Album Art of Music Files. Please suggest a solution for this if Possible.!

antoninastefanowska commented 3 years ago

Like I said, the reason might be that the album image is simply too large for react native Image. There is also a possibility that you have to wait quite a while for the image to be properly loaded and rendered.

Album covers aren't usually that big, so I think most of them should render fine. For a temporary workaround, I would suggest implementing image loading placeholder (there an interesting tutorial here: https://medium.com/react-native-training/progressive-image-loading-in-react-native-e7a01827feb7).