ffmpeg + Spotify APIで音楽ファイルのアートワークを自動埋め込みするGoツール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208038/873540af-b28e-4dad-b81e-89b563f02ad7.png)

こうなってる音源のアートワークを表示させるスクリプトを作りました。
clineで作ってますが結構ハマったので最終的に力技っぽくなっています。

各OSごとにビルドしてあるので、README.mdを参考に動かしてみてください。

ffmpegコマンドはこちらを参考
https://pianoforte32.com/using-ffmpeg-to-do-meta-tag-including-artwork-in-audio-files/

## 機能

- 音楽ファイルのメタデータ（アーティスト・アルバム情報）を自動抽出
- Spotify APIを使用したアートワーク画像の自動検索
- 高品質な画像の自動ダウンロード
- ffmpegを使用したアートワークの音楽ファイルへの埋め込み
- ディレクトリ内の複数ファイルの一括処理
- メタデータ不足ファイルのスキップ機能

## 対応フォーマット

- MP3 (.mp3)
- M4A (.m4a)
- FLAC (.flac)
- WAV (.wav)

## 必要な環境

### 1. ffmpegのインストール

#### macOS
```bash
# Homebrewを使用
brew install ffmpeg
```

#### Ubuntu/Debian
```bash
sudo apt update
sudo apt install ffmpeg
```

#### CentOS/RHEL/Rocky Linux
```bash
# EPELリポジトリを有効化
sudo dnf install epel-release
sudo dnf install ffmpeg
```

#### Windows
1. [公式サイト](https://ffmpeg.org/download.html)からWindows版をダウンロード
2. 解凍してPATHに追加
3. または以下のパッケージマネージャーを使用：
```powershell
# Chocolateyを使用
choco install ffmpeg

# Scoopを使用
scoop install ffmpeg
```

#### Arch Linux
```bash
sudo pacman -S ffmpeg
```

### 2. Go言語の環境
Go 1.21以上が必要です。

### 3. Spotify API認証情報
[Spotify Developer Console](https://developer.spotify.com/dashboard/)でアプリケーションを作成し、Client IDとClient Secretを取得してください。

## セットアップ

### 1. リポジトリのクローンと依存関係のインストール
```bash
git clone <repository-url>
cd music-artwork-embedder
go mod tidy
```

### 2. Spotify API認証情報の設定
```bash
export SPOTIFY_CLIENT_ID="your_spotify_client_id"
export SPOTIFY_CLIENT_SECRET="your_spotify_client_secret"
```

Windows（PowerShell）の場合：
```powershell
$env:SPOTIFY_CLIENT_ID="your_spotify_client_id"
$env:SPOTIFY_CLIENT_SECRET="your_spotify_client_secret"
```

## 使用方法

### 単一ファイルの処理
```bash
go run main.go /path/to/music/file.mp3
```

### ディレクトリ全体の一括処理
```bash
go run main.go /path/to/music/directory
```

### 実行可能ファイルとしてビルド
```bash
go build -o music-artwork-embedder
./music-artwork-embedder /path/to/music/file.mp3
```

## Spotify Developer Console設定手順

1. [Spotify Developer Console](https://developer.spotify.com/dashboard/)にアクセス
2. Spotifyアカウントでログイン
3. 「Create App」をクリック
4. アプリ情報を入力：
    - App name: 任意の名前
    - App description: 任意の説明
    - Redirect URI: `http://localhost` (使用しないが必須)
    - API/SDKs: Web API にチェック
5. 作成後、「Settings」から Client ID と Client Secret を取得
## アーキテクチャ

### 概要

orchestratorがfacadeっぽく各クラスを利用する設計にしています。
依存方向とかは気にしてません。

### ディレクトリ構造

```
.
├── .env.local                    # 環境変数設定ファイル
├── .gitignore                    # Git除外設定
├── go.mod                        # Go モジュール定義
├── go.sum                        # 依存関係チェックサム
├── go_build.sh                   # ビルドスクリプト
├── main.go                       # アプリケーションエントリーポイント
├── README.md                     # プロジェクト説明書
└── src/                          # ソースコードディレクトリ
    ├── args/                     # コマンドライン引数処理
    │   └── args.go
    ├── artwork/                  # アートワーク処理
    │   ├── ffmpeg_commands.go    # ffmpegコマンド実行
    │   └── processor.go          # アートワーク処理ロジック
    ├── config/                   # 設定管理
    │   └── config.go
    ├── fileutils/                # ファイル操作ユーティリティ
    │   └── fileutils.go
    ├── metadata/                 # メタデータ処理
    │   ├── extractor.go          # メタデータ抽出
    │   └── filename_parser.go    # ファイル名解析
    ├── orchestrator/             # 処理統合・制御
    │   └── orchestrator.go
    └── spotify/                  # Spotify API連携
        ├── client.go             # APIクライアント
        └── types.go              # データ型定義
```

### パッケージ詳細

#### `args` - コマンドライン引数処理
- **責務**: コマンドライン引数の解析と設定管理
- **主要構造体**: `Config`
- **主要関数**: `ParseArgs()`

#### `config` - 設定管理
- **責務**: アプリケーション設定と環境変数の管理
- **主要構造体**: `Config`
- **主要関数**: `NewConfig()`, `LoadEnv()`, `ValidateSpotifyCredentials()`

#### `spotify` - Spotify API連携
- **責務**: Spotify Web APIとの通信とアートワーク検索
- **主要構造体**: `Client`, `SpotifySearchResponse`
- **主要関数**: `NewClient()`, `GetToken()`, `SearchArtwork()`

#### `metadata` - メタデータ処理
- **責務**: 音楽ファイルのメタデータ抽出とファイル名解析
- **主要関数**: `ExtractMetadata()`, `ExtractTitleFromFilename()`

#### `artwork` - アートワーク処理
- **責務**: 画像ダウンロード、フォーマット検出、ffmpegによる埋め込み
- **主要構造体**: `Processor`
- **主要関数**: `NewProcessor()`, `DownloadImage()`, `EmbedArtwork()`, `EmbedArtworkForceReplace()`

#### `fileutils` - ファイル操作ユーティリティ
- **責務**: ファイルのバックアップ、復元、検証、ディレクトリ処理
- **主要関数**: `CreateBackup()`, `RestoreFromBackup()`, `ValidateAudioFile()`, `ProcessDirectory()`

#### `orchestrator` - 処理統合・制御
- **責務**: 各パッケージの協調と全体的な処理フローの制御
- **主要構造体**: `Orchestrator`
- **主要関数**: `NewOrchestrator()`, `Initialize()`, `ProcessFile()`, `ProcessDirectory()`

### クラス図（構造体関係）

```mermaid
classDiagram
    class ArgsConfig {
        +bool ForceOverwrite
        +ParseArgs() (string, *Config, error)
    }
    
    class ConfigConfig {
        +bool ForceOverwrite
        +string SpotifyClientID
        +string SpotifyClientSecret
        +NewConfig(bool) *Config
        +LoadEnv() error
        +ValidateSpotifyCredentials() error
    }
    
    class SpotifyClient {
        -string accessToken
        -http.Client httpClient
        +NewClient() *Client
        +GetToken(string, string) error
        +SearchArtwork(string, string) (string, error)
    }
    
    class SpotifySearchResponse {
        +Tracks struct
    }
    
    class ArtworkProcessor {
        -http.Client httpClient
        +NewProcessor() *Processor
        +DownloadImage(string, string) error
        +GetAudioFormat(string) (string, error)
        +HasExistingArtwork(string) (bool, error)
        +EmbedArtwork(string, string, string) error
        +EmbedArtworkForceReplace(string, string, string) error
    }
    
    class Orchestrator {
        -ConfigConfig config
        -SpotifyClient spotifyClient
        -ArtworkProcessor artworkProcessor
        +NewOrchestrator(*Config) *Orchestrator
        +Initialize() error
        +ProcessFile(string) error
        +ProcessDirectory(string) error
    }
    
    Orchestrator --> ConfigConfig : uses
    Orchestrator --> SpotifyClient : uses
    Orchestrator --> ArtworkProcessor : uses
    SpotifyClient --> SpotifySearchResponse : returns
```

### パッケージ依存関係図

```mermaid
graph TD
    A[main.go] --> B[args]
    A --> C[config]
    A --> D[orchestrator]
    
    D --> C
    D --> E[spotify]
    D --> F[artwork]
    D --> G[fileutils]
    D --> H[metadata]
    
    E --> I[spotify/types]
    E --> J[spotify/client]
    
    F --> K[artwork/processor]
    F --> L[artwork/ffmpeg_commands]
    
    H --> M[metadata/extractor]
    H --> N[metadata/filename_parser]
    
    style A fill:#e1f5fe
    style D fill:#f3e5f5
    style C fill:#e8f5e8
    style E fill:#fff3e0
    style F fill:#fce4ec
    style G fill:#f1f8e9
    style H fill:#e0f2f1
```

## 動作の流れ

### 全体的な処理フロー

1. **初期化**: `main.go`でコマンドライン引数を解析し、設定を読み込み
2. **オーケストレーター作成**: 各パッケージのインスタンスを生成・注入
3. **Spotify認証**: API認証トークンを取得
4. **ファイル処理**: 指定されたファイル/ディレクトリを処理

### 単一ファイル処理の詳細フロー

1. **バックアップ作成**: `fileutils`パッケージで元ファイルをバックアップ
2. **既存アートワーク確認**: `artwork`パッケージで既存アートワークの有無を確認
3. **メタデータ抽出**: `metadata`パッケージでアーティスト・アルバム・タイトル情報を抽出
4. **フォールバック処理**: メタデータ不足時にファイル名から情報を抽出
5. **アートワーク検索**: `spotify`パッケージでSpotify APIを使用して画像を検索
6. **画像ダウンロード**: `artwork`パッケージで最高品質の画像をダウンロード
7. **アートワーク埋め込み**: `artwork`パッケージでffmpegを使用して画像を埋め込み
8. **ファイル検証**: `fileutils`パッケージで出力ファイルの整合性を確認
9. **ファイル置換**: 元ファイルを処理済みファイルで置換
10. **クリーンアップ**: バックアップファイルと一時ファイルを削除