MP3 檔案包含 MPEG 音訊框架 (標頭、側資料、主資料) 與選用的 ID3 標籤 (v1 在檔尾 128 bytes,v2 在檔頭)。本類別提供統一介面提取標題、藝術家、專輯、年份、流派、封面圖片、比特率、取樣率、長度等資訊。
<?php
class MP3 {
private $filePath;
private $fileHandle;
private $fileSize;
private $info = []; // MPEG 框架資訊
private $id3v1 = []; // ID3v1 標籤
private $id3v2 = []; // ID3v2 標籤 (支援 2.2/2.3/2.4)
private $id3v2Offset = 0;
public function __construct($filePath) {
$this->filePath = $filePath;
$this->fileSize = filesize($filePath);
$this->fileHandle = fopen($filePath, 'rb');
if (!$this->fileHandle) throw new Exception("無法開啟檔案: $filePath");
}
public function __destruct() {
if ($this->fileHandle) fclose($this->fileHandle);
}
// 公開介面
public function getInfo() {
if (empty($this->info)) $this->parseMpeg();
return $this->info;
}
public function getID3() {
if (empty($this->id3v1) && empty($this->id3v2)) $this->parseID3();
return array_merge($this->id3v1, $this->id3v2); // v2 優先覆蓋 v1
}
// 內部解析方法...
private function parseMpeg() { /* 掃描框架同步字 0xFFE/0xFFF,解析標頭 */ }
private function parseID3() {
$this->parseID3v2(); // 檔頭
$this->parseID3v1(); // 檔尾
}
private function parseID3v1() { /* 讀取最後 128 bytes,標記 "TAG" */ }
private function parseID3v2() {
// 檢查 "ID3" 標識,解析版本、旗標、大小 (synchsafe int)
// 迴圈讀取框架: TIT2 (標題), TPE1 (藝術家), TALB (專輯), TYER (年份), TCON (流派), APIC (封面), 等
// 支援 UTF-16 (BOM), UTF-8, ISO-8859-1 編碼
}
private function readSynchsafeInt($bytes) { /* 7位元編碼整數 */ }
private function readFrame($maxOffset) { /* 解析單一 ID3v2 框架 */ }
}
// 使用範例
$mp3 = new MP3('song.mp3');
$info = $mp3->getInfo();
$id3 = $mp3->getID3();
echo "標題: {$id3['title']}\n";
echo "藝術家: {$id3['artist']}\n";
echo "專輯: {$id3['album']}\n";
echo "比特率: {$info['bitrate']} kbps\n";
echo "取樣率: {$info['sample_rate']} Hz\n";
echo "長度: {$info['playtime_string']}\n";
if (!empty($id3['cover'])) {
file_put_contents('cover.jpg', $id3['cover']);
echo "封面已擷取: cover.jpg\n";
}
?>
| 項目 | 規格來源 | 解析重點 |
|---|---|---|
| MPEG 框架同步 | ISO/IEC 11172-3 | 尋找 0xFFF (11 bits) 或 0xFFE,解析版本、層、比特率索引、取樣率索引、填充、模式 |
| 比特率計算 | MPEG-1 Layer III 表 | 查表獲取 kbps,VBR 需掃描多框架平均或讀取 Xing/Info 標頭 |
| ID3v1 | 非官方標準 | 檔尾 128 bytes: "TAG" + 30字標題 + 30字藝術家 + 30字專輯 + 4字年份 + 30字備註 + 1字流派 |
| ID3v2 大小 | id3.org | Synchsafe integer: 4 bytes, 每 byte 最高位為 0, 實際 28 bits |
| ID3v2 框架 | ID3v2.3.0 / 2.4.0 | Frame ID (4 chars) + Size (4 bytes) + Flags (2 bytes) + Data |
| 文字編碼 | ID3v2.3/2.4 | 第一 byte: 0=ISO-8859-1, 1=UTF-16 (BOM), 2=UTF-16BE, 3=UTF-8 |
| 封面圖片 (APIC) | ID3v2 | MIME 類型 + 圖片類型 + 描述 + 圖片二進位資料 |
| 方案 | 優點 | 缺點 |
|---|---|---|
| getID3() 庫 | 功能最完整、支援超多格式、活躍維護 | 體積大 (~2MB)、純 PHP 效能一般 |
| ffprobe (FFmpeg) | 極快、準確、支援所有編碼器、可提取波形圖 | 需安裝 FFmpeg、執行外部程序、安全性考量 |
| PHP-FFMpeg | 物件導向封裝 ffprobe/ffmpeg | 依賴外部二進制檔 |
| Node.js music-metadata | 快速、原生非同步、TypeScript 支援 | 需 Node 環境 |
fseek/fread 逐塊處理。audio/mpeg)、副檔名、檔案大小限制。unlink 上傳暫存檔。MP3 中繼資料解析涉及複雜的二進位格式與多版本相容,生產環境強烈建議使用成熟庫 (getID3) 或外部工具 (ffprobe),自行實作僅適合教學或極簡需求。