5

如何使用 delphi 编辑 mp3 文件详细信息,例如描述、标题、副标题、评级、艺术家等。有什么组件可以做到这一点吗?

谢谢

4

5 回答 5

6

您可能不仅可以操作 ID3V1,还可以操作 ID3V2。

所以,这是可以帮助你的图书馆

http://www.3delite.hu/Object Pascal 开发者资源/id3v2library.html

于 2010-11-23T20:27:43.073 回答
2

我不记得我是从哪里得到这个单元的,但我不久前将它用于一个宠物项目:

unit ID3v2;

interface

uses
   Classes, SysUtils;

const
   TAG_VERSION_2_3 = 3;                               { Code for
ID3v2.3.0 tag }

type
   { Class TID3v2 }
   TID3v2 = class(TObject)
     private
       { Private declarations }
       FExists: Boolean;
       FVersionID: Byte;
       FSize: Integer;
       FTitle: string;
       FArtist: string;
       FAlbum: string;
       FTrack: Byte;
       FYear: string;
       FGenre: string;
       FComment: string;
     public
       { Public declarations }
       constructor Create;                                     { Create
object }
       procedure ResetData;                                   { Reset
all data }
       function ReadFromFile(const FileName: string): Boolean;      {
Load tag }
       property Exists: Boolean read FExists;              { True if tag
found }
       property VersionID: Byte read FVersionID;                {
Version code }
       property Size: Integer read FSize;                     { Total
tag size }
       property Title: string read FTitle;                        { Song
title }
       property Artist: string read FArtist;                     {
Artist name }
       property Album: string read FAlbum;                        {
Album name }
       property Track: Byte read FTrack;                        { Track
number }
       property Year: string read FYear;
{ Year }
       property Genre: string read FGenre;                        {
Genre name }
       property Comment: string read FComment;                       {
Comment }
   end;

implementation

const
   { Max. number of supported tag frames }
   ID3V2_FRAME_COUNT = 7;

   { Names of supported tag frames }
   ID3V2_FRAME: array [1..ID3V2_FRAME_COUNT] of string =
     ('TIT2', 'TPE1', 'TALB', 'TRCK', 'TYER', 'TCON', 'COMM');

type
   { ID3v2 frame header }
   FrameHeader = record
     ID: array [1..4] of AnsiChar;                                      {
Frame ID }
     Size: Integer;                                    { Size excluding
header }
     Flags: Word;                                                      {
Flags }
   end;

   { ID3v2 header data - for internal use }
   TagInfo = record
     { Real structure of ID3v2 header }
     ID: array [1..3] of AnsiChar;                                  { Always
"ID3" }
     Version: Byte;                                           { Version
number }
     Revision: Byte;                                         { Revision
number }
     Flags: Byte;                                               { Flags
of tag }
     Size: array [1..4] of Byte;                   { Tag size excluding
header }
     { Extended data }
     FileSize: Integer;                                    { File size
(bytes) }
     Frame: array [1..ID3V2_FRAME_COUNT] of string;  { Information from
frames }
   end;

{ ********************* Auxiliary functions & procedures
******************** }

function ReadHeader(const FileName: string; var Tag: TagInfo): Boolean;
var
   SourceFile: file;
   Transferred: Integer;
begin
   try
     Result := true;
     { Set read-access and open file }
     AssignFile(SourceFile, FileName);
     FileMode := 0;
     Reset(SourceFile, 1);
     { Read header and get file size }
     BlockRead(SourceFile, Tag, 10, Transferred);
     Tag.FileSize := FileSize(SourceFile);
     CloseFile(SourceFile);
     { if transfer is not complete }
     if Transferred < 10 then Result := false;
   except
     { Error }
     Result := false;
   end;
end;

{
---------------------------------------------------------------------------

}

function GetVersionID(const Tag: TagInfo): Byte;
begin
   { Get tag version from header }
   Result := Tag.Version;
end;

{
---------------------------------------------------------------------------

}

function GetTagSize(const Tag: TagInfo): Integer;
begin
   { Get total tag size }
   Result :=
     Tag.Size[1] * $200000 +
     Tag.Size[2] * $4000 +
     Tag.Size[3] * $80 +
     Tag.Size[4] + 10;
   if Result > Tag.FileSize then Result := 0;
end;

{
---------------------------------------------------------------------------

}

procedure SetTagItem(const ID, Data: string; var Tag: TagInfo);
var
   Iterator: Byte;
begin
   { Set tag item if supported frame found }
   for Iterator := 1 to ID3V2_FRAME_COUNT do
     if ID3V2_FRAME[Iterator] = ID then Tag.Frame[Iterator] := Data;
end;

{
---------------------------------------------------------------------------

}

function Swap32(const Figure: Integer): Integer;
var
   ByteArray: array [1..4] of Byte absolute Figure;
begin
   { Swap 4 bytes }
   Result :=
     ByteArray[1] * $100000000 +
     ByteArray[2] * $10000 +
     ByteArray[3] * $100 +
     ByteArray[4];
end;

{
---------------------------------------------------------------------------

}

procedure ReadFrames(const FileName: string; var Tag: TagInfo);
var
   SourceFile: file;
   Frame: FrameHeader;
   Data: array [1..250] of AnsiChar;
   DataPosition: Integer;
begin
   try
     { Set read-access, open file }
     AssignFile(SourceFile, FileName);
     FileMode := 0;
     Reset(SourceFile, 1);
     Seek(SourceFile, 10);
     while (FilePos(SourceFile) < GetTagSize(Tag)) and (not
EOF(SourceFile)) do
     begin
       FillChar(Data, SizeOf(Data), 0);
       { Read frame header }
       BlockRead(SourceFile, Frame, 10);
       DataPosition := FilePos(SourceFile);
       { Read frame data and set tag item if frame supported }
       BlockRead(SourceFile, Data, Swap32(Frame.Size) mod SizeOf(Data));
       SetTagItem(Frame.ID, Data, Tag);
       Seek(SourceFile, DataPosition + Swap32(Frame.Size));
     end;
     CloseFile(SourceFile);
   except
   end;
end;

{
---------------------------------------------------------------------------

}

function GetTrack(const TrackString: string): Byte;
var
   Index, Value, Code: Integer;
begin
   { Extract track from string }
   Index := Pos('/', TrackString);
   if Index = 0 then Val(Trim(TrackString), Value, Code)
   else Val(Copy(Trim(TrackString), 1, Index), Value, Code);
   if Code = 0 then Result := Value
   else Result := 0;
end;

{
---------------------------------------------------------------------------

}

function GetGenre(const GenreString: string): string;
begin
   { Extract genre from string }
   Result := Trim(GenreString);
   if Pos(')', Result) > 0 then Delete(Result, 1, LastDelimiter(')',
Result));
end;

{ ********************** Public functions & procedures
********************** }

constructor TID3v2.Create;
begin
   inherited;
   ResetData;
end;

{
---------------------------------------------------------------------------

}

procedure TID3v2.ResetData;
begin
   FExists := false;
   FVersionID := 0;
   FSize := 0;
   FTitle := '';
   FArtist := '';
   FAlbum := '';
   FTrack := 0;
   FYear := '';
   FGenre := '';
   FComment := '';
end;

{
---------------------------------------------------------------------------

}

function TID3v2.ReadFromFile(const FileName: string): Boolean;
var
   Tag: TagInfo;
begin
   { Reset data and load header from file to variable }
   ResetData;
   Result := ReadHeader(FileName, Tag);
   { Process data if loaded and header valid }
   if (Result) and (Tag.ID = 'ID3') then
   begin
     FExists := true;
     { Fill properties with header data }
     FVersionID := GetVersionID(Tag);
     FSize := GetTagSize(Tag);
     { Get information from frames if version supported }
     if (FVersionID = TAG_VERSION_2_3) and (FSize > 0) then
     begin
       ReadFrames(FileName, Tag);
       { Fill properties with data from frames }
       FTitle :=  Trim(Tag.Frame[1]);
       FArtist := Trim(Tag.Frame[2]);
       FAlbum := Trim(Tag.Frame[3]);
       FTrack := GetTrack(Tag.Frame[4]);
       FYear := Trim(Tag.Frame[5]);
       FGenre := GetGenre(Tag.Frame[6]);
       FComment := Trim(Copy(Tag.Frame[7], 5, Length(Tag.Frame[7]) - 4));
     end;
   end;
end;

end. 
于 2010-11-23T21:17:10.053 回答
1

看看id3mgmnt.pas,它看起来像你的目的。

从未测试过,只是发布了第一个谷歌结果。

于 2010-11-23T19:58:35.757 回答
1

您可以使用来自http://www.delphi-jedi.org/的 TJvID3v1 或 TJvID3v2 组件

于 2010-11-24T03:22:05.563 回答
1

不久前,我使用了 Jürgen Faul 的音频工具库的一部分。它有点旧(2002 年),但是这个库一直由其他人维护到 2005 年。您可以从各种组件存储库中获取旧的 2002 版本,或者从http://mac.sourceforge.net/atl获取“最新”版本/。我不知道这些是否符合最新的 ID3 标准,但 2002 代码仍然从我的旧音频播放器项目的 MP3 文件中获取数据。

@ioan:您发布的单元实际上来自该库的某个版本。

于 2010-11-24T20:38:05.620 回答