# メディアライブラリへのハードリンク 内蔵プラグイン `hardlink` は、トレントの整理が終わると、本編と字幕を別のメディアライブラリフォルダにリンクします。ダウンロードフォルダはそのまま残り、トレントはシードを続けます。メディアサーバーはライブラリフォルダだけをスキャンします。 このプラグインは**既定で無効**です。各トレントの整理が終わった後に実行されます。リネーム方式が `none` のときも実行されます。 ## 有効にする 1. **設定 → プラグイン** を開き、`hardlink` プラグインの **設定** を展開します。 2. `source_root`(ダウンロードのルート)と `library_root`(メディアライブラリ)を入力します。どちらも AB から見た絶対パスです。`library_root` は `source_root` の中に置けません。 3. ダウンローダーから見たパスが AB と異なる場合は、`path_map` に行を追加します(後述)。 4. **設定を保存** をクリックし、次に **有効** スイッチをオンにします。 カードの状態が「実行中」になれば動作しています。保存時に AB は設定を検証します。パスが絶対パスでない場合や、ライブラリがダウンロードのルートの中にある場合は保存されません。 ライブラリ内のパスは、ファイルの `source_root` からの相対パスと同じです: ``` source_root /media/downloads/Bangumi library_root /media/library /media/downloads/Bangumi/葬送のフリーレン (2023)/Season 1/葬送のフリーレン S01E05.mkv >> /media/library/葬送のフリーレン (2023)/Season 1/葬送のフリーレン S01E05.mkv ``` ## オプション | オプション | 説明 | 既定値 | | --- | --- | --- | | `source_root` | ダウンロードのルート。AB 側の絶対パス。ライブラリは同じフォルダ構造になります | なし、必須 | | `library_root` | メディアライブラリ。AB 側の絶対パス。`source_root` の中に置けません | なし、必須 | | `path_map` | ダウンローダーのパスを AB のパスに変換する対応表。後述 | 空 | | `cross_device` | ファイルシステムをまたぐとき:`copy` はコピー、`symlink` はシンボリックリンク、`skip` はスキップして通知 | `copy` | ## パスの対応表 「整理完了」イベントのファイルパスは**ダウンローダーから見たパス**です。ダウンローダーと AB が別々のコンテナで動き、マウント先が異なる場合は、`path_map` で AB のパスに変換します。 各行には 3 つの項目があります: - `downloader`:ダウンローダーインスタンスの id。既定は `default`。ダウンローダーインスタンスごとに行が必要です。[複数のダウンローダー](./downloaders.md)を参照してください。 - `from`:ダウンローダーから見たパスの接頭辞。 - `to`:同じ場所を AB から見たパス。 AB はイベントと同じダウンローダー id の行だけを使い、最長一致の接頭辞を選びます。一致しないパスはそのまま使います。 例:qBittorrent はディスクを `/downloads` としてマウントし、AB は同じディスクを `/media/downloads` としてマウントしています。2 台目のダウンローダー `nas` からは `/volume1/downloads` に見えます: ```json "path_map": [ { "downloader": "default", "from": "/downloads", "to": "/media/downloads" }, { "downloader": "nas", "from": "/volume1/downloads", "to": "/media/nas" } ] ``` 設定フォームでは **行を追加** で対応を追加し、**削除** で行を削除します。 変換後のパスは `source_root` の中になければなりません。そうでない場合、AB はそのファイルを処理せず、通知を送ります。 ## 別ドライブと Docker ハードリンクは同じファイルシステム内でしか作れません。`source_root` と `library_root` が別のファイルシステムにある場合、AB は `cross_device` に従います: - `copy`(既定):ファイルをコピーし、更新日時を保持します。ライブラリが同じ容量をもう一度使います。大きなファイルはコピーに時間がかかります。 - `symlink`:シンボリックリンクを作ります。ダウンロードフォルダのファイルを削除すると、リンクは切れます。 - `skip`:処理せず、通知を送ります。 ::: tip Docker ダウンロードフォルダとライブラリを同じディスクに置き、**1 つのマウントポイント**で AB コンテナにマウントしてください。例えば `/mnt/media` 全体を `/media` としてマウントし、ダウンロードフォルダとライブラリをその下に置きます。別々にマウントした 2 つのフォルダは、同じディスク上でも別のファイルシステムとして扱われ、`cross_device` に従います。 ::: AB はまずリンクまたはコピーを目的ファイルの隣の一時ファイル(`.<ファイル名>.<ランダム文字列>.ab-hardlink`)に書き、その後アトミックに目的のファイル名に変更します。コピーが途中で止まっても、ライブラリに不完全なファイルは残りません。 ## ライブラリに既にファイルがある場合 プラグインは、ライブラリに置いた各ファイルを記録します。目的の場所に既にファイルがある場合: | 状況 | 結果 | | --- | --- | | 目的のファイルがソースのハードリンク、シンボリックリンク、または同じコピー | 完了済みとみなし、何もしません | | プラグインが置いたファイルではない、または置いた後に別のファイルに変わった | スキップし、**上書きしません**。通知を送ります | | プラグインが同じ場所に置いた古いファイル | バージョンアップ。新しいファイルにアトミックに置き換えます | **バージョンアップ**:新しいバージョンのトレント(例:`v2`)が古いトレントを置き換えても、整理後のファイル名は変わりません。プラグインは以前のリンクを新しいファイルへのリンクに置き換えます。 1 つのトレントの問題はすべて 1 件の「ハードリンク未完了」通知にまとめられ、ファイルごとに理由が表示されます。通知にはトレント名ではなくトレントのハッシュが表示されます。 ## 既存のファイルをリンクする プラグインは、有効にした後に整理されたトレントだけを処理します。有効にする前にダウンロードしたファイルは、手動でリンクします: 1. **設定** を開き、セクション一覧の末尾にある「Hardlink backfill」(ハードリンク補完)を探します。このセクションはプラグインの実行中だけ表示されます。 2. **Link existing files**(既存ファイルをリンク)をクリックします。 AB は `source_root` 以下の `.mp4`、`.mkv`、`.ass`、`.srt` ファイルを探し、リンク済み・既存・衝突・失敗の 4 つの件数を表示します。補完はクリックしたときだけ実行され、通知は送りません。リンク済みのファイルは再処理しません。補完は AB 側のダウンロードのルートを直接読むため、`path_map` は使いません。 `POST /api/v1/plugins/hardlink/backfill` を呼んでも同じ件数が返ります。 ## トレントの削除 トレントを削除しても、ライブラリ内のファイルは削除されません。ハードリンクまたはコピーの場合、トレントとそのファイルを削除してもライブラリのファイルは再生できます。シンボリックリンクの場合、リンクは切れます。