私は巨大な音楽コレクションを持っています。それらのいくつかはロスレスファイルであり、いくつかは損失のあるファイルです。
元のコレクションの損失ファイルと、元のコレクションのロスレスファイルの損失のトランスコードを含むコレクションのコピーを維持したいと思います。
いくつかの仮定:
- 私はffmpegを使ってflacをopusファイルに変換する方法を知っています。
- 変換する必要があるflacファイルのみがあり、wavまたはalacコーデックはありません。
- 損失ファイルはopus、vorbis、またはmp3です。
私が欲しい:
- 最小限のストレージを使用して新しい音楽コレクションを保存します。つまり、適切な場合は元の損失ファイルに再接続されます。
- 元のファイルに失われたファイルとロスレスファイルを追加するか、メタデータを更新するので、コレクションを最新の状態に保ちます。
- 変更されていないロスレスファイルを再トランスコードする必要はありません。
これを行うには、いくつかのカスタムスクリプトを使用する必要があるようですが、多くの時間を費やす前に誰もが提案やヒントを持っている場合は永遠に感謝します。
答え1
私はMakefileが好きではありません(同意することもできます)これ男);ただし、make
デフォルトでは必要に応じて行われます。
.opus
たとえば、すべてのソースファイル.flac
に対してファイルを希望するルールを定義します。
Makefile、私の心から
TARGETDIR=/path/to/compressed/library
%.opus: %.flac
ffmpeg -ffmpegflags -and -stuff -i "$<" -o "$@"
$(TARGETDIR)/%.opus: %.opus
cp --reflink=always "$<" "$@"
これにより、ツリー内のすべてのFLACがOPUSに変換されます。 .opusファイルがまだ存在しない場合、またはFLACの最後の変更より古い場合にのみこれを実行します。
私はそれがツリー内で発生するので気に入らない。つまり、きれいな「オリジナルのみ」ディレクトリでは終わりません。少なくともcp
参照リンクをサポートするファイルシステムを使用してコピーを浅くし、実際にスペースを必要としないようにしてください。私の考えでは、サブディレクトリも正常に処理できないようです。
それなら正直に言って make がすることは実際には次のようになります。
各ワイルドカードソースファイル(%.flac)に対して結果(同じファイル.opus)がビルドされていることを確認し、そうでない場合(またはビルドがソースファイルより古い)ビルドします。
これはやや逆になっており、Makeに頼る必要があるほど複雑ではありません。だから、シェルスクリプト。 zshを使用しています。私が書いた内容をテストしませんが、これについてコメントしました。
#!/usr/bin/zsh
# Copyright 2022 Marcus Müller
# SPDX-License-Identifier: BSD-3-Clause
# Find the license text under https://spdx.org/licenses/BSD-3-Clause.html
# set options:
setopt null_glob # Don't fail if there's no file matching a pattern
setopt no_case_glob # Don't care about case in matching
TARGET_DIR=../compressed_library
make_containing_dir() {
target_dir="${1:h}"
if [[ ! -d "${target_dir}" ]] ; then
logger -p user.debug "Creating directory ${target_dir}"
mkdir -p "${target_dir}" || logger -p user.err "can't mkdir ${target_dir}"
}
for compressed_source in **/*.{mp3,opus,vorbis,mp4} ; do
if [[ -d "${compressed_source}" ]]; then
continue # skip directories that happen to have a matching suffix
fi
logger -p user.debug "dealing with compressed source ${compressed_source}"
target_file="${TARGET_DIR}/${compressed_source}"
make_containing_dir "${target_file}"
# -h : check whether target exists and is symlink
if [[ ! -h "${target_file}" ]] ; then
ln -s "$(pwd)/${compressed_source}" "${target_file}" \
|| logger -p user.err "copying ${compressed_source} failed"
fi
done
for uncompressed_source in **/*.flac ; do
if [[ -d "${uncompressed_source}" ]]; then
continue # skip directories that happen to have a matching suffix
fi
logger -p user.debug "dealing with uncompressed source ${compressed_source}"
target_file="${TARGET_DIR}/${uncompressed_source%%.flac}.opus"
# ^ strip the .flac suffix
make_containing_dir "${target_file}"
# /-- compare source file for "older than"
# | target file; this returns !=0 if the source file
# | is newer, or the target file nonexisting
# \--------------------\
# |
if [[ "${uncompressed_source}" -ot "${target_file}" ]]; then
ffmpeg -loglevel=fatal \
-i "${uncompressed_source}" \
-b:a 96k \
"${target_file}" \
|| logger -p user.err "transcoding ${uncompressed_source} failed"
fi
done
これは非常にテストされていませんが、少なくともシステムログに記録されます(journalctl -xef
あなたの友達です)。