kiwilan / php-audio
PHP 包,用于解析和更新音频文件元数据,包含 `JamesHeinrich/getID3`。
Requires
- php: ^8.1
- james-heinrich/getid3: ^1.9
Requires (Dev)
- laravel/pint: ^1.2
- pestphp/pest: ^1.20
- spatie/ray: ^1.28
README
PHP 包,用于解析和更新音频文件元数据,包含 JamesHeinrich/getID3
。
注意
您可以在“支持格式”部分检查支持的格式。
关于
音频文件可以使用不同的格式,本包旨在提供一个简单的方法来读取它们,使用 JamesHeinrich/getID3
。该 JamesHeinrich/getID3
包非常适合从音频文件中读取元数据,但输出仅是一个数组,当前包旨在提供一个简单的方法来读取音频文件,具有美观的 API。
要求
- PHP >= 8.1
- 更新时可选
FLAC
:flac
(通过apt
,brew
或scoop
)OGG
:vorbis-tools
(通过apt
或brew
) /extras/icecast
(通过scoop
)
路线图
- 通过外部包添加更多格式的支持 外部包
安装
您可以通过 composer 安装此包
composer require kiwilan/php-audio
用法
核心元数据
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getTitle(); // `?string` to get title $audio->getArtist(); // `?string` to get artist $audio->getAlbum(); // `?string` to get album $audio->getGenre(); // `?string` to get genre $audio->getYear(); // `?int` to get year $audio->getTrackNumber(); // `?string` to get track number $audio->getComment(); // `?string` to get comment $audio->getAlbumArtist(); // `?string` to get album artist $audio->getComposer(); // `?string` to get composer $audio->getDiscNumber(); // `?string` to get disc number $audio->isCompilation(); // `bool` to know if is compilation $audio->getCreationDate(); // `?string` to get creation date (audiobook) $audio->getCopyright(); // `?string` to get copyright (audiobook) $audio->getEncoding(); // `?string` to get encoding $audio->getDescription(); // `?string` to get description (audiobook) $audio->getPodcastDescription(); // `?string` to get podcast description (audiobook) $audio->getLanguage(); // `?string` to get language $audio->getLyrics(); // `?string` (audiobook) $audio->getStik(); // `?string` (audiobook) $audio->getDuration(); // `?float` to get duration in seconds
原始标签
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getTags(); // `array` with all tags $title = $audio->getTag('title'); // `?string` to get title same as `$audio->getTitle()` $formats = $audio->getAudioFormats(); // `array` with all audio formats $format = $audio->getTags('id3v2'); // `?array` with all tags with format `id3v2` $title = $audio->getTag('title', 'id3v2'); // `?string` to get title with format `id3v2`
附加元数据
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getPath(); // `string` to get path $audio->hasCover(); // `bool` to know if has cover $audio->isValid(); // `bool` to know if file is valid audio file $audio->getFormat(); // `AudioFormatEnum` to get format (mp3, m4a, ...) $audio->getType(); // `?AudioTypeEnum` ID3 type (id3, riff, asf, quicktime, matroska, ape, vorbiscomment) $audio->getExtras(); // `array` with raw metadata (could contains some metadata not parsed)
原始音频
注意
封面已从 toArray()
方法中移除,您可以使用 getCover()
方法获取封面元数据。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->toArray(); // `array` with all metadata
高级属性
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getReader(); // `?Id3Reader` reader based on `getID3` $audio->getWriter(); // `?Id3Writer` writer based on `getid3_writetags` $audio->getStat(); // `AudioStat` (from `stat` function) $audio->getAudio(); // `?AudioMetadata` with audio metadata $audio->getCover(); // `?AudioCover` with cover metadata
更新
您可以使用 Audio::class
更新音频文件元数据,但并非所有格式都受支持。 查看支持格式
警告
您可以使用 Audio::class
的任何属性,但如果您使用格式不支持的属性,它将被忽略。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getTitle(); // `Title` $tag = $audio->update() ->title('New Title') ->artist('New Artist') ->album('New Album') ->genre('New Genre') ->year('2022') ->trackNumber('2/10') ->albumArtist('New Album Artist') ->comment('New Comment') ->composer('New Composer') ->creationDate('2021-01-01') ->description('New Description') ->discNumber('2/2') ->encodingBy('New Encoding By') ->encoding('New Encoding') ->isCompilation() ->lyrics('New Lyrics') ->stik('New Stik') ->cover('path/to/cover.jpg') // you can use file content `file_get_contents('path/to/cover.jpg')` ->save(); $audio = Audio::get('path/to/audio.mp3'); $audio->getTitle(); // `New Title` $audio->getCreationDate(); // `null` because `creationDate` is not supported by `MP3`
某些属性不是所有格式都支持,例如,MP3
无法处理一些属性,如 lyrics
或 stik
,如果您尝试更新这些属性,它们将被忽略。
手动设置标签
您可以使用 tags
方法手动设置标签,但您需要知道标签的格式,您可以使用 tagFormats
设置标签的格式(如果您不知道格式,它将被自动检测)。
警告
如果您使用 tags
方法,您必须使用元数据容器使用的键。例如,如果您想在 id3v2
中设置专辑艺术家,您必须使用 band
键。如果您想了解使用哪个键,请检查 src/Models/AudioCore.php
文件。
如果您的键不受支持,则 save
方法将抛出异常,除非您使用 preventFailOnErrors
。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getAlbumArtist(); // `Band` $tag = $audio->update() ->tags([ 'title' => 'New Title', 'band' => 'New Band', // `band` is used by `id3v2` to set album artist, method is `albumArtist` but `albumArtist` key will throw an exception with `id3v2` ]) ->tagFormats(['id3v1', 'id3v2.4']) // optional ->save(); $audio = Audio::get('path/to/audio.mp3'); $audio->getAlbumArtist(); // `New Band`
箭头函数
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getAlbumArtist(); // `Band` $tag = $audio->update() ->title('New Title') ->albumArtist('New Band') // `albumArtist` will set `band` for `id3v2`, exception safe ->save(); $audio = Audio::get('path/to/audio.mp3'); $audio->getAlbumArtist(); // `New Band`
防止错误失败
您可以使用 preventFailOnError
来防止在使用不受支持的格式时抛出异常。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $tag = $audio->update() ->tags([ 'title' => 'New Title', 'title2' => 'New title', // not supported by `id3v2`, will throw an exception ]) ->preventFailOnError() // will prevent exception ->save();
箭头函数对于属性是异常安全的,但对于不受支持的格式则不是。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $tag = $audio->update() ->encoding('New encoding') // not supported by `id3v2`, BUT will not throw an exception ->preventFailOnError() // if you have some errors with unsupported format for example, you can prevent exception ->save();
标签和封面
当然,您可以使用 tags
方法添加封面。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $cover = 'path/to/cover.jpg'; $image = getimagesize($cover); $coverData = file_get_contents($cover); $coverPicturetypeid = $image[2]; $coverDescription = 'cover'; $coverMime = $image['mime']; $tag = $audio->update() ->tags([ 'title' => 'New Title', 'band' => 'New Band', 'attached_picture' => [ [ 'data' => $coverData, 'picturetypeid' => $coverPicturetypeid, 'description' => $coverDescription, 'mime' => $coverMime, ], ], ]) ->save();
合并标签
使用箭头函数合并 tags
。
use Kiwilan\Audio\Audio; $audio = Audio::get($path); $tag = $audio->update() ->title('New Title') // will be merged with `tags` and override `title` key ->tags([ 'title' => 'New Title tag', 'band' => 'New Band', ]); $tag->save(); $audio = Audio::get($path); expect($audio->getTitle())->toBe('New Title'); expect($audio->getAlbumArtist())->toBe('New Band');
额外功能
使用不同方法处理音频文件格式元数据,JamesHeinrich/getID3
提供了通过不同方法检查这些元数据的功能。在 Audio::class
的 extras
属性中,您将找到来自 JamesHeinrich/getID3
包的原始元数据,如 id3v2
、id3v1
、riff
、asf
、quicktime
、matroska
、ape
、vorbiscomment
等。
如果您想提取可以被 Audio::class
跳过的特定字段,您可以使用 extras
属性。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $extras = $audio->getExtras(); $id3v2 = $extras['id3v2'] ?? [];
AudioMetadata
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getAudio()->getFilesize(); // `?int` in bytes $audio->getAudio()->getExtension(); // `?string` (mp3, m4a, ...) $audio->getAudio()->getEncoding(); // `?string` (UTF-8...) $audio->getAudio()->getMimeType(); // `?string` (audio/mpeg, audio/mp4, ...) $audio->getAudio()->getDurationSeconds(); // `?float` in seconds $audio->getAudio()->getDurationReadable(); // `?string` (00:00:00) $audio->getAudio()->getBitrate(); // `?int` in kbps $audio->getAudio()->getBitrateMode(); // `?string` (cbr, vbr, ...) $audio->getAudio()->getSampleRate(); // `?int` in Hz $audio->getAudio()->getChannels(); // `?int` (1, 2, ...) $audio->getAudio()->getChannelMode(); // `?string` (mono, stereo, ...) $audio->getAudio()->getLossless(); // `bool` to know if is lossless $audio->getAudio()->getCompressionRatio(); // `?float`
AudioCover
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $audio->getCover()->getContents(); // `?string` raw file $audio->getCover()->getMimeType(); // `?string` (image/jpeg, image/png, ...) $audio->getCover()->getWidth(); // `?int` in pixels $audio->getCover()->getHeight(); // `?int` in pixels
支持的格式
可读格式
- 如果同时提供
id3v2
、id3v1
或riff
,则id3v2
将在id3v1
或riff
之前被选中。
您想添加一个格式? 查看常见问题解答
可更新的格式
JamesHeinrich/getID3
可以更新一些格式,但并非所有格式。
- ID3v1 (v1 & v1.1)
- ID3v2 (v2.3, v2.4)
- APE (v2)
- Ogg Vorbis 注释(需要
vorbis-tools
)- FLAC 注释(需要
flac
)
flac
:通过apt
、brew
或scoop
vorbis-tools
:通过apt
、brew
或scoop
- 使用
scoop
时,vorbis-tools
不可用,您可以使用extras/icecast
代替。
- 使用
转换属性
Audio::class
将一些属性转换为更易读的形式。
测试
composer test
工具
- ffmpeg:由一系列库和程序组成的免费开源软件项目,用于处理视频、音频和其他多媒体文件和流。
- MP3TAG:一款强大且易于使用的工具,用于编辑音频文件的元数据(Windows上免费)。
- Audiobook Builder:轻松将音频 CD 和文件转换为有声读物(仅限 macOS 和付费)。
- Tag Editor:一个具有 Qt 图形界面和命令行界面的标签编辑器,支持 MP4/M4A/AAC(iTunes)、ID3、Vorbis、Opus、FLAC 和 Matroska。
- Tag Editor:一个电子表格应用程序,用于以简单、快速和灵活的方式编辑音频元数据。
常见问题解答
我的音频文件中有一个特定的元数据字段,我该怎么办?
在 Audio::class
中,您有一个包含所有原始元数据的 extras
属性,如果 JamesHeinrich/getID3
支持此字段,您将在此属性中找到它。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $extras = $audio->getExtras(); $custom = null; $id3v2 = $extras['id3v2'] ?? []; if ($id3v2) { $custom = $id3v2['custom'] ?? null; }
如果您的字段可以添加到 Audio::class
的全局属性中,您可以创建一个 问题。
元数据为 null
,我该怎么办?
您可以通过检查 extras
属性来了解是否有一些元数据可用。
use Kiwilan\Audio\Audio; $audio = Audio::get('path/to/audio.mp3'); $extras = $audio->getExtras(); var_dump($extras);
如果您发现 Audio::class
未解析的元数据,您可以创建一个 问题,否则 JamesHeinrich/getID3
不支持此元数据。
我不支持的格式是我的最爱,我该怎么办?
您可以创建一个 问题,包括格式名称和格式文档的链接。如果 JamesHeinrich/getID3
支持此格式,我将将其添加到此包中,但如果您想贡献,您可以为格式实现创建一个 pull request。
请给我一个测试格式的示例文件。
我对一个支持的格式有问题,我该怎么办?
您可以根据信息创建一个 问题。
如何转换音频文件?
此包不提供转换音频文件的方法,但您可以使用 ffmpeg 转换音频文件和 PHP-FFMpeg/PHP-FFMpeg。
变更日志
请参阅变更日志获取关于最近更改的更多信息。
鸣谢
- Ewilan Rivière:软件包作者
- JamesHeinrich/getID3:用于读取音频文件的解析器
- spatie/package-skeleton-php:创建此软件包所使用的软件包骨架
- 测试文件来自p1pdd.com(第00集)
许可协议
MIT许可协议(MIT)。有关更多信息,请参阅许可文件。