kiwilan/php-audio

PHP 包,用于解析和更新音频文件元数据,包含 `JamesHeinrich/getID3`。

资助包维护!
kiwilan

3.0.08 2024-07-28 13:47 UTC

This package is auto-updated.

Last update: 2024-08-28 13:59:53 UTC


README

Banner with speaker and PHP Audio title

php version downloads license tests codecov

PHP 包,用于解析和更新音频文件元数据,包含 JamesHeinrich/getID3

注意

您可以在“支持格式”部分检查支持的格式。

关于

音频文件可以使用不同的格式,本包旨在提供一个简单的方法来读取它们,使用 JamesHeinrich/getID3。该 JamesHeinrich/getID3 包非常适合从音频文件中读取元数据,但输出仅是一个数组,当前包旨在提供一个简单的方法来读取音频文件,具有美观的 API。

要求

  • PHP >= 8.1
  • 更新时可选
    • FLAC: flac (通过 apt, brewscoop)
    • OGG: vorbis-tools (通过 aptbrew) / 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 无法处理一些属性,如 lyricsstik,如果您尝试更新这些属性,它们将被忽略。

手动设置标签

您可以使用 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::classextras 属性中,您将找到来自 JamesHeinrich/getID3 包的原始元数据,如 id3v2id3v1riffasfquicktimematroskaapevorbiscomment 等。

如果您想提取可以被 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

支持的格式

可读格式

  • 如果同时提供 id3v2id3v1riff,则 id3v2 将在 id3v1riff 之前被选中。

您想添加一个格式? 查看常见问题解答

可更新的格式

JamesHeinrich/getID3 可以更新一些格式,但并非所有格式。

  • ID3v1 (v1 & v1.1)
  • ID3v2 (v2.3, v2.4)
  • APE (v2)
  • Ogg Vorbis 注释(需要 vorbis-tools
  • FLAC 注释(需要 flac
  • flac:通过 aptbrewscoop
  • vorbis-tools:通过 aptbrewscoop
    • 使用 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

变更日志

请参阅变更日志获取关于最近更改的更多信息。

鸣谢

许可协议

MIT许可协议(MIT)。有关更多信息,请参阅许可文件