如何编辑 mp3 文件详细信息 (Delphi)

发布于 2024-10-04 05:05:23 字数 81 浏览 0 评论 0 原文

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

谢谢

How can i edit mp3 file details , such as Description , Title , Subtitle , Rating , Artist , ... using delphi . is there any component to do this ?

Thank you

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

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

发布评论

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

评论(5

诗酒趁年少 2024-10-11 05:05:23

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

所以,这个库可以帮助您

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

You may probably be able to manipulate not only ID3V1 but ID3V2 as well.

so, this is library that may help you

http://www.3delite.hu/Object Pascal Developer Resources/id3v2library.html

赢得她心 2024-10-11 05:05:23

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

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. 

I don't remember where I got this unit from, but I used it for a pet project a while ago:

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. 
写给空气的情书 2024-10-11 05:05:23

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

You can use TJvID3v1 or TJvID3v2 components from http://www.delphi-jedi.org/

旧城空念 2024-10-11 05:05:23

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

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

I used parts of Jürgen Faul's Audio Tools Library a while ago. It's a bit old (2002), but this library has been maintained by other people until 2005. You can get the old 2002 version from various component repositories or get the "latest" one from http://mac.sourceforge.net/atl/. I don't know if these are up to the latest ID3 standard, but the 2002 code still fetches data from MP3 files for my old audio player project.

@ioan: the unit you posted comes actually from some version of this library.

猛虎独行 2024-10-11 05:05:23

看看id3mgmnt.pas,看起来像什么你是为了.

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

编辑:使用新的 Google 结果刷新了链接(13 年后)。我现在明白只发布链接是个坏主意,但我也无法在这里重现整个单元代码,所以我决定现在更新链接,存储库位于: github.com/tiensitu86/kspnew/

Take a look at id3mgmnt.pas, it looks like what you're for.

Never tested it, just publishing first google result.

Edit: Refreshed the link with the new google result (13 years later). I now understand it was bad idea to publish just the link, but I cannot reproduce the entire unit code here also, so I decided to just update the link now, the repository was found on: github.com/tiensitu86/kspnew/.

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