テレビ録画メディアサーバー構築入門(第13回)
ライブラリ
メディアサーバーにおけるライブラリ機能とは、簡単に言うと、動画、音楽、写真などのメディアファイルを整理・管理するための機能です。
EPGStationなどの既存のテレビ録画サーバーでは、このライブラリ機能が不足している点が課題です。録画サーバーにも一定のニーズがあることを踏まえ、本稿「テレビ録画メディアサーバー構築入門」では、録画サーバーとメディアサーバー両者の機能的な役割を活かして、視聴体験の向上を最大化することを目指しています。
前回,Jellyfin(メディアサーバー)で録画動画を公開データベースと自動連携させる方法を紹介しました.自動連携の仕方は,「番組」と「映画」では異なります。さらに,アニメのように,別のデータベースを参照したい場合も生じます.こうした場合を想定して,Jellyfinでは複数のタイプの「ライブラリ」が準備されています.
ライブラリ機能を利用する最初のステップとして、テレビ放送された映画(番組)は「映画」として扱いたい。
たとえば、「金曜ロードショー」では、各回に1つの映画作品が放送されますが、これは「番組」の1つの「エピソード」として扱うよりも,「映画」として、独立させて取り扱う方が自然な分類になります.
「映画」を別扱いする
Jellyfinで異なるライブラリとして分類するには,サーバー上の保存ディレクトリを別にする必要があります.これまで「番組」の動画ファイル(mp4)を ~/media に置いたので,「映画」は ~/movies に置くことにします.
mp4の出力先を分けたことに対応して,m2tsの出力先も2か所に分けます.通常番組は ~/docker-mirakurun-epgstation/recorded でしたので,映画は ~/docker-mirakurun-epgstation/recorded2 に書き出すことにします.
トランスコード作業は「番組」と「映画」で並列的に処理することになります。作業ディレクトリも,「番組」の ~/work に対して,「映画」には ~/work2 を新たに用意します.
作業としては、ディレクトリをコピーして,設定に少し手を加えて、Mirakurun/EPGStation/Jellyfin を再起動します。
手順1: EPGStation
まず、EPGStation を止めて,
cd docker-mirakurun-epgstation
sudo docker-compose down2つの設定ファイルに, recorded2を追記します.
エディターnanoで編集するなら、nano docker-compose.yml
epgstation:
build:
context: "./epgstation"
dockerfile: "debian.Dockerfile"
volumes:
- ./epgstation/config:/app/config
- ./epgstation/data:/app/data
- ./epgstation/thumbnail:/app/thumbnail
- ./epgstation/logs:/app/logs
- ./recorded:/app/recorded
- ./recorded2:/app/recorded2最後の1行が新たに追加したものです.直前の行 - ./recorded:/app/recorded をコピーして2か所のrecordedの末尾に「2」を加えました.
同様にして、nano epgstation/config/config.yml
recorded:
- name: recorded
path: '%ROOT%/recorded'
- name: recorded2
path: '%ROOT%/recorded2'最後の2行が追記分.
EPGStation を起動して、設定を反映させる。
sudo docker-compose up -dサーバーが起動したら、EPGStation の「ルール」(検索)から,「映画」の出力ディレクトリを「recorded2」にして「更新」。(「映画」用に複数のルール項目を設定しているなら、すべて recorded2に変更する。)
手順2: 新 作業ディレクトリ
作業ディレクトリをコピーする.
cd
cp -r work work2
cd work2
echo >encode.logまず、ディレクトリwork2の中の2つのファイル: enc01.sh、gbsize_toprocess.sh の SOURCEDIR を recordedから recorded2に変更する.
nano enc01.sh
nano gbsize_toprocess.sh
SOURCEDIR="$HOME/docker-mirakurun-epgstation/recorded2/"次に、enc01.sh の OUTDIR を media から movies に変更
enc01.sh:OUTDIR="$HOME/movies/"さらに、remove_empty_dirs.sh と update_thumbs.sh の MEDIA_ROOT も同様に変更する。
MEDIA_ROOT="$HOME/movies/"同じように、enc01.sh
WORKDIR="$HOME/work2/"そして、encode.sh
SCRIPT="$HOME/work2/enc01.sh" #実行スクリプト
totalsize=$($HOME/work2/gbsize_toprocess.sh) #処理すべきファイルサイズ[Gb]以上、変更終了。
注意点として,python スクリプト中の work は 変更しない:
processed.py: PROCESSED_FILE = os.path.expanduser("~") + "/work/processed_filenames.json"
toprocess.py: PROCESSED_FILE = os.path.expanduser("~") + "/work/processed_filenames.json"
ここの work は変更しない.処理済み番組カタログ(PROCESSED_FILE)は、元の作業ディレクトリ ~/work で一元的に管理するためです.
mvjf.sh (映画版)
番組用のもの(第7回)とは異なり,「映画」では,番組名 PROGRAM (例:金曜ロードショー)は不要なので省略して,映画作品名 EPISODE のディレクトリを~/movies直下に作り,そこに動画ファイルを移動するように、work2ディレクトリの mvjf.sh を以下のものに置き換えます。
~/work2/mvjf.sh:
#!/bin/bash
# 入力ファイル名と出力ディレクトリを受け取る
input_file="$1"
outdir="$2"
# 区切り文字のリストを定義する(連想配列を使用)
declare -A delimiter_pairs=(
["「"]="」"
["『"]="』"
)
# 必要な引数が不足している場合のエラーハンドリング
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <input_file> <output_directory>"
exit 1
fi
# ファイルが存在するかどうかチェック
if [ ! -f "$input_file" ]; then
echo "指定されたファイルが存在しません: $input_file"
exit 1
fi
# 出力ディレクトリが存在するかどうかチェック
if [ ! -d "$outdir" ]; then
echo "指定された出力ディレクトリが存在しません: $outdir"
exit 1
fi
## ファイル名からディレクトリとファイルパスを構築
FILENAME=$(basename "$input_file")
# 最初の区切り文字までをPROGRAMとし、その後の部分から次の区切り文字までの部分をEPISODEとする
for delimiter in "${!delimiter_pairs[@]}"; do
# 初めて現れる区切り文字で分割
IFS="$delimiter" read -ra parts <<< "$FILENAME"
if [ ${#parts[@]} -gt 1 ]; then
PROGRAM="${parts[0]}"
rest="${parts[*]:1}"
# 対応するセカンドデリミタを取得
second_delimiter=${delimiter_pairs[$delimiter]}
# 次の区切り文字までの部分をEPISODEとする
IFS="$second_delimiter" read -ra second_parts <<< "$rest"
if [ ${#second_parts[@]} -gt 0 ]; then
EPISODE="${second_parts[0]}"
fi
fi
done
# 結果を表示する
echo "PROGRAM: $PROGRAM"
echo "EPISODE: $EPISODE"
# 最終的なディレクトリパスを構築
#final_dir="$outdir/$PROGRAM/$EPISODE"
final_dir="$outdir/$EPISODE"
# ディレクトリを作成(存在しない場合のみ)
mkdir -p "$final_dir" || {
echo "ディレクトリの作成に失敗しました: $final_dir"
exit 1
}
# ファイルを移動
mv "$input_file" "$final_dir" || {
echo "ファイルの移動に失敗しました: $input_file -> $final_dir"
exit 1
}
echo "ファイルが正常に移動されました: crontabに追記する
「番組」の encode.sh と同じように、「映画」のトランスコードを定期的(4分おき)に実行させる。
crontab -e
*/4 * * * * sleep 2m;$HOME/work2/encode.sh >> $HOME/work2/encode.log 2>&1手順3: Jellyfin
停止してから、削除して、新設定を加えて起動しなおす。
sudo docker stop jellyfin
sudo docker rm jellyfin
sudo docker rmi jellyfin/jellyfin
mkdir movies
sudo docker run -d --name jellyfin --user 1000:1000 --net=host --volume ./jellyfin/config:/config --volume ./jellyfin/cache:/cache --mount type=bind,source=./media,target=/media --mount type=bind,source=./movies,target=/movies --restart=unless-stopped --volume /usr/share/fonts:/usr/share/fonts --volume /usr/share/fontconfig:/usr/share/fontconfig jellyfin/jellyfin:10.10.7(2025/11/7追記: 末尾にバージョン10.10.7を追加。Jellyfinは10/19に最新安定版10.11.0がリリースされた。大型アップデートのため、最新版に更新すると、バックアップなしでは、旧版には戻せない(新規インストールが必要となる)。基本機能が安定するまでは、10.10.7の使用を推奨します。)
サーバーが起動したら、クライエント(http://100.x.y.z:8096)から「映画」ライブラリを新規設定する。
Jellyfin 「ダッシュボード」の「ライブラリ」から「ライブラリ」を選択し、「メディアライブラリーを追加」
コンテンツタイプ:映画
フォルダ:「+」より /movies を選択
優先するダウンロード言語:Japanese
国/地域: Japan
メタデータダウンローダー:すべて(TheMovieDb) にチェック
件のイメージを取得:すべてチェック
アートワークをメディアフォルダに保存:チェック
サムネ更新
映画作品は TMDBに登録されている可能性が高いので,enc01.sh 末尾の サムネ更新 (update_thumbs.sh) はコメントアウトしてもよいでしょう.
~/work2/enc01.sh: (ファイル末尾)
#$encoded && $WORKDIR/update_thumbs.sh
サムネ画像は、ないと見た目が悪いのですが、自前で用意したものが存在すると、「現在の画像を置き換える」で「ライブラリスキャン」しないと、見栄えのよいデータベース版は上書きダウンロードされません.
「番組」~/work/ についても、同じように変更します。あなたの録画コレクションの(ほぼ)すべてが、データベースに登録されている番組であれば、動画処理のたびにサムネ画像をつくる必要はありません(上記同様、update_thumbs.sh行をコメントアウト)。
そのかわり、「番組」については、定期的に実行することに。
crontab -e
29 12 * * * $HOME/work/update_thumbs.sh >> $HOME/work/encode.log 2>&1
12時29分である必要はないのですが。。
結果
さて、ここまで準備すると、放置しておくだけで,映画メディアコレクションが全自動で貯まっていきます.
データベース連携
映画作品は The Movie DataBase (TMDB) に登録されている可能性が高い。
データベースに登録されている(しかし誤認識する)のならば、動画メタデータを手作業で編集すれば、正しく認識されるようになります。
「映画」の場合は、外部IDを空欄、タイトル(題)に加えて、「年」が重要になります。マイナーな海外作品ならば「原題」も。
あるいは、TMDBサイトで直接検索して、番組・映画ページのURLから ID (数値部分だけ:「-」以降の作品名は除く)を読み取り、「TheMovieDb シリーズ(ムービー) ID」に入力して、「リフレッシュ」。ちなみに、画像が気に入らないなら、「イメージを編集」から検索・選択可能。
日本の録画界隈や世界の Jellyfinユーザーにとっては、アニメ作品が特別な地位を占めています。「番組」「映画」に加えて「アニメ番組」と「アニメ映画」を、ライブラリとして独立させるケースが多いようです。
専用データベースとの連携(どのデータベースを優先的に参照するか等)は、Jellyfinの人気プラグインの重要な一角を占めています。技術的には、データベース連携こそが、ライブラリ機能の主用な目的になります。



コメント