使用 TagLib 从 MP3 文件中提取 GUID

发布于 2024-12-11 23:18:35 字数 734 浏览 0 评论 0原文

所以,我的最终目标是从我的音频文件中获取专辑封面。我正在使用 taglib 和 c++。我找到了有关如何提取嵌入图像数据的信息,但 Windows Media Player 似乎没有嵌入图像本身。相反,它会保存名为 AlbumArt_{E3208100-4FAA-4030-BB9D-6DA5F9D93D18}_Large.jpg 之类的 jpg。显然它使用了一个 guid,我相信它保存在 PRIV 标签中。我向你们提出的问题是我怎样才能到达它?我认为这样的事情可能会起作用:

    ID3v2::PrivateFrame* privFrame = static_cast<ID3v2::PrivateFrame*>(*privIter);
    if(privFrame != NULL)
    {
        std::string owner = privFrame->owner().toCString();
        if (owner == "WM/WMCollectionID" || owner == "WM/WMCollectionGroupID")
        {
            const char* data = privFrame->render().data();
            GUID guid;
            memcpy(&guid.Data1, data, sizeof(long));
        }
    }

但数据似乎没有任何有用的东西。有什么想法吗?

so, my end game is getting album art from my audio files. i'm using taglib and c++. i've found info about how to extract embedded image data, but it seems windows media player does not embed the image itself. instead, it saves a jpg named something like AlbumArt_{E3208100-4FAA-4030-BB9D-6DA5F9D93D18}_Large.jpg. clearly it's using a guid, which i believe it saves in a PRIV tag. my question to you folks is how can i get to it? i thought something like this might work:

    ID3v2::PrivateFrame* privFrame = static_cast<ID3v2::PrivateFrame*>(*privIter);
    if(privFrame != NULL)
    {
        std::string owner = privFrame->owner().toCString();
        if (owner == "WM/WMCollectionID" || owner == "WM/WMCollectionGroupID")
        {
            const char* data = privFrame->render().data();
            GUID guid;
            memcpy(&guid.Data1, data, sizeof(long));
        }
    }

but data doesn't seem to have anything useful. any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴骨ら 2024-12-18 23:18:35

对于那些有类似问题的人,据我所知 taglib 的 PrivateFrame 已损坏。因此,我推出了自己的:

bool MetadataReader::getAlbumGUID(const char* filename, GUID &guid)
{
    const int HEADER_LENGTH = 10;
    const int TAG_INDICATOR_LENGTH = 3;
    const string TAG_TYPE = "ID3";
    const int TAG_MAJOR = 3;
    const int TAG_MINOR = 0;
    const int HEADER_SIZE_BEGIN = 6;
    const int HEADER_SIZE_END = 9;
    const int EXTENDED_HEADER_POS = 5;
    const int EXTENDED_HEADER_SIZE_LENGTH = 4;
    const int FRAME_HEADER_LENGTH = 10;
    const int FRAME_ID_LENGTH = 4;
    const string FRAME_MEDIA_PLAYER_OWNER1 = "WM/WMCollectionID";
    const string FRAME_MEDIA_PLAYER_OWNER2 = "WM/WMCollectionGroupID";
    const string FRAME_MEDIA_PLAYER_ID = "PRIV";
    const int FRAME_SIZE_BEGIN = 4;
    const int FRAME_SIZE_END = 7;


    bool retValue = false;
    try
    {
        // read in file
        ifstream infile(filename, ios::binary);

        infile.seekg(0, ios::beg);

        char header[HEADER_LENGTH];
        infile.read(header, HEADER_LENGTH);

        string tagType(TAG_INDICATOR_LENGTH, '0');
        for (int i = 0; i < TAG_INDICATOR_LENGTH; i++)
        {
            tagType[i] = header[i];
        }
        int majorVersion = (int)header[TAG_INDICATOR_LENGTH];
        int minorVersion = (int)header[TAG_INDICATOR_LENGTH + 1];
        if (tagType == TAG_TYPE && majorVersion == TAG_MAJOR && minorVersion == TAG_MINOR)
        {
            // get extended header bit
            bool extHeader = (header[EXTENDED_HEADER_POS] & 0x0010000);

            // get size of extended header
            int extHeaderSize = 0;
            if (extHeader)
            {
                char extHeaderData[EXTENDED_HEADER_SIZE_LENGTH];
                infile.seekg(HEADER_LENGTH, ios::beg);
                infile.read(extHeaderData, EXTENDED_HEADER_SIZE_LENGTH);
                for (int i = 0; i <= EXTENDED_HEADER_SIZE_LENGTH; i++)
                {
                    extHeaderSize = extHeaderSize << 8;
                    extHeaderSize |= (unsigned char)extHeaderData[i];
                }
                extHeaderSize += EXTENDED_HEADER_SIZE_LENGTH;

            }
            // get size of tag.
            // 4 bytes with the most significant bit ignored
            int tagSize = 0;
            for (int i = HEADER_SIZE_BEGIN; i <= HEADER_SIZE_END; i++)
            {
                tagSize = tagSize << 7;
                tagSize |= (header[i] & 0x7f);
            }
            // tagSize includes extended header
            tagSize += HEADER_LENGTH;

            // read tags
            int currPos = HEADER_LENGTH + extHeaderSize;
            while (currPos < tagSize)
            {
                infile.seekg(currPos, ios::beg);

                char frameHeader[FRAME_HEADER_LENGTH];
                infile.read(frameHeader, FRAME_HEADER_LENGTH);

                // frame id
                string frameType(FRAME_ID_LENGTH, '0');
                for (int i = 0; i < FRAME_ID_LENGTH; i++)
                {
                    frameType[i] = frameHeader[i];
                }
                // frame length
                int frameLength = 0;
                for (int i = FRAME_SIZE_BEGIN; i <= FRAME_SIZE_END; i++)
                {
                    frameLength = frameLength << 8;
                    frameLength |= (unsigned char)frameHeader[i];
                }
                if (frameType == FRAME_MEDIA_PLAYER_ID)
                {
                    char* frameData = new char[frameLength];
                    infile.read(frameData, frameLength);
                    string owner = frameData;
                    if (owner == FRAME_MEDIA_PLAYER_OWNER1 || owner == FRAME_MEDIA_PLAYER_OWNER2)
                    {
                        memcpy(&guid, frameData + owner.length() + 1, sizeof(GUID));
                        retValue = true;
                    }
                    delete[] frameData;
                }

                currPos += FRAME_HEADER_LENGTH + frameLength;
            }
            infile.close();
        }
    }
    catch (...)
    {
        retValue = false;
    }

    return retValue;
}

for those with similar problems, as far as i can tell taglib's PrivateFrame is broken. thus, i have rolled my own:

bool MetadataReader::getAlbumGUID(const char* filename, GUID &guid)
{
    const int HEADER_LENGTH = 10;
    const int TAG_INDICATOR_LENGTH = 3;
    const string TAG_TYPE = "ID3";
    const int TAG_MAJOR = 3;
    const int TAG_MINOR = 0;
    const int HEADER_SIZE_BEGIN = 6;
    const int HEADER_SIZE_END = 9;
    const int EXTENDED_HEADER_POS = 5;
    const int EXTENDED_HEADER_SIZE_LENGTH = 4;
    const int FRAME_HEADER_LENGTH = 10;
    const int FRAME_ID_LENGTH = 4;
    const string FRAME_MEDIA_PLAYER_OWNER1 = "WM/WMCollectionID";
    const string FRAME_MEDIA_PLAYER_OWNER2 = "WM/WMCollectionGroupID";
    const string FRAME_MEDIA_PLAYER_ID = "PRIV";
    const int FRAME_SIZE_BEGIN = 4;
    const int FRAME_SIZE_END = 7;


    bool retValue = false;
    try
    {
        // read in file
        ifstream infile(filename, ios::binary);

        infile.seekg(0, ios::beg);

        char header[HEADER_LENGTH];
        infile.read(header, HEADER_LENGTH);

        string tagType(TAG_INDICATOR_LENGTH, '0');
        for (int i = 0; i < TAG_INDICATOR_LENGTH; i++)
        {
            tagType[i] = header[i];
        }
        int majorVersion = (int)header[TAG_INDICATOR_LENGTH];
        int minorVersion = (int)header[TAG_INDICATOR_LENGTH + 1];
        if (tagType == TAG_TYPE && majorVersion == TAG_MAJOR && minorVersion == TAG_MINOR)
        {
            // get extended header bit
            bool extHeader = (header[EXTENDED_HEADER_POS] & 0x0010000);

            // get size of extended header
            int extHeaderSize = 0;
            if (extHeader)
            {
                char extHeaderData[EXTENDED_HEADER_SIZE_LENGTH];
                infile.seekg(HEADER_LENGTH, ios::beg);
                infile.read(extHeaderData, EXTENDED_HEADER_SIZE_LENGTH);
                for (int i = 0; i <= EXTENDED_HEADER_SIZE_LENGTH; i++)
                {
                    extHeaderSize = extHeaderSize << 8;
                    extHeaderSize |= (unsigned char)extHeaderData[i];
                }
                extHeaderSize += EXTENDED_HEADER_SIZE_LENGTH;

            }
            // get size of tag.
            // 4 bytes with the most significant bit ignored
            int tagSize = 0;
            for (int i = HEADER_SIZE_BEGIN; i <= HEADER_SIZE_END; i++)
            {
                tagSize = tagSize << 7;
                tagSize |= (header[i] & 0x7f);
            }
            // tagSize includes extended header
            tagSize += HEADER_LENGTH;

            // read tags
            int currPos = HEADER_LENGTH + extHeaderSize;
            while (currPos < tagSize)
            {
                infile.seekg(currPos, ios::beg);

                char frameHeader[FRAME_HEADER_LENGTH];
                infile.read(frameHeader, FRAME_HEADER_LENGTH);

                // frame id
                string frameType(FRAME_ID_LENGTH, '0');
                for (int i = 0; i < FRAME_ID_LENGTH; i++)
                {
                    frameType[i] = frameHeader[i];
                }
                // frame length
                int frameLength = 0;
                for (int i = FRAME_SIZE_BEGIN; i <= FRAME_SIZE_END; i++)
                {
                    frameLength = frameLength << 8;
                    frameLength |= (unsigned char)frameHeader[i];
                }
                if (frameType == FRAME_MEDIA_PLAYER_ID)
                {
                    char* frameData = new char[frameLength];
                    infile.read(frameData, frameLength);
                    string owner = frameData;
                    if (owner == FRAME_MEDIA_PLAYER_OWNER1 || owner == FRAME_MEDIA_PLAYER_OWNER2)
                    {
                        memcpy(&guid, frameData + owner.length() + 1, sizeof(GUID));
                        retValue = true;
                    }
                    delete[] frameData;
                }

                currPos += FRAME_HEADER_LENGTH + frameLength;
            }
            infile.close();
        }
    }
    catch (...)
    {
        retValue = false;
    }

    return retValue;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文