comment lib/decode/* (#LLM-assisted - Claude Code)
This commit is contained in:
parent
22549072c3
commit
6474bcab25
@ -1,12 +1,34 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
|
# soxtaskid persists across destinations so encode tasks share a single sox task
|
||||||
declare soxtaskid
|
declare soxtaskid
|
||||||
decodeFile() {
|
decodeFile() {
|
||||||
|
# copy destinations bypass decoding entirely
|
||||||
if [[ ${destinationformat["$destination"]} == copy ]]
|
if [[ ${destinationformat["$destination"]} == copy ]]
|
||||||
then
|
then
|
||||||
copied=1
|
copied=1
|
||||||
else
|
else
|
||||||
|
# Dispatch to the appropriate decoder based on the source
|
||||||
|
# MIME type.
|
||||||
|
# sox_needed is set when normalization, resampling, or channel
|
||||||
|
# up/downmixing is required. Used to determine whether to
|
||||||
|
# insert an intermediate sox processing task.
|
||||||
case "$mimetype" in
|
case "$mimetype" in
|
||||||
'video/'*)
|
'video/'*)
|
||||||
|
# Extract audio if ffmpeg is available
|
||||||
(( disablevideo )) && continue
|
(( disablevideo )) && continue
|
||||||
extractAudio
|
extractAudio
|
||||||
if (( ${destinationnormalize["$destination"]}))\
|
if (( ${destinationnormalize["$destination"]}))\
|
||||||
@ -22,6 +44,8 @@ decodeFile() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
'audio/mpeg')
|
'audio/mpeg')
|
||||||
|
# Copy MP3 as-is if format and quality match
|
||||||
|
# otherwise decode with sox
|
||||||
if [[ ${destinationformat[$destination]} = mp3 ]] \
|
if [[ ${destinationformat[$destination]} = mp3 ]] \
|
||||||
&& checkCopy
|
&& checkCopy
|
||||||
then
|
then
|
||||||
@ -30,7 +54,9 @@ decodeFile() {
|
|||||||
decodeSox
|
decodeSox
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
'application/ogg opus')
|
'application/ogg opus'|'audio/ogg opus')
|
||||||
|
# Copy Opus as-is if format and quality match
|
||||||
|
# otherwise decode with opusdec
|
||||||
if [[ ${destinationformat[$destination]} = opus ]] \
|
if [[ ${destinationformat[$destination]} = opus ]] \
|
||||||
&& checkCopy
|
&& checkCopy
|
||||||
then
|
then
|
||||||
@ -51,28 +77,9 @@ decodeFile() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
'audio/ogg opus')
|
'application/ogg'*|'audio/ogg'*)
|
||||||
if [[ ${destinationformat[$destination]} = opus ]] \
|
# Ogg Vorbis: copy if format/quality match
|
||||||
&& checkCopy
|
# otherwise decode with sox
|
||||||
then
|
|
||||||
copied=1
|
|
||||||
else
|
|
||||||
(( disableopusdec )) && continue
|
|
||||||
decodeOpusdec
|
|
||||||
if (( ${destinationnormalize["$destination"]}))\
|
|
||||||
|| (
|
|
||||||
[ -n "${destinationfrequency["$destination"]}" ]\
|
|
||||||
&& (( ${rate:-0} != ${destinationfrequency["$destination"]}))\
|
|
||||||
) || (
|
|
||||||
[ -n "${destinationchannels["$destination"]}" ]\
|
|
||||||
&& (( ${channels:-0} != ${destinationchannels["$destination"]} ))
|
|
||||||
)
|
|
||||||
then
|
|
||||||
sox_needed=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
'application/ogg'*)
|
|
||||||
if [[ ${destinationformat[$destination]} = vorbis ]] \
|
if [[ ${destinationformat[$destination]} = vorbis ]] \
|
||||||
&& checkCopy
|
&& checkCopy
|
||||||
then
|
then
|
||||||
@ -81,22 +88,14 @@ decodeFile() {
|
|||||||
decodeSox
|
decodeSox
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
'audio/ogg'*)
|
'audio/x-flac'|'audio/flac')
|
||||||
if [[ ${destinationformat[$destination]} = vorbis ]] \
|
# FLAC: always decode via sox
|
||||||
&& checkCopy
|
# copy for FLAC makes little sense
|
||||||
then
|
|
||||||
copied=1
|
|
||||||
else
|
|
||||||
decodeSox
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
'audio/x-flac')
|
|
||||||
decodeSox
|
|
||||||
;;
|
|
||||||
'audio/flac')
|
|
||||||
decodeSox
|
decodeSox
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
# Unknown MIME type: probe with file to detect
|
||||||
|
# Musepack
|
||||||
extendedtype=$(file -b "$sourcepath/$filename")
|
extendedtype=$(file -b "$sourcepath/$filename")
|
||||||
case "$extendedtype" in
|
case "$extendedtype" in
|
||||||
*'Musepack '*)
|
*'Musepack '*)
|
||||||
@ -115,6 +114,9 @@ decodeFile() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
# Truly unknown format: try
|
||||||
|
# ffmpeg if available,
|
||||||
|
# otherwise fall back to sox
|
||||||
if (( disablevideo ))
|
if (( disablevideo ))
|
||||||
then
|
then
|
||||||
decodeSox
|
decodeSox
|
||||||
@ -138,6 +140,10 @@ decodeFile() {
|
|||||||
esac
|
esac
|
||||||
if ! (( copied ))
|
if ! (( copied ))
|
||||||
then
|
then
|
||||||
|
# Insert a decode task if one doesn't already exist for
|
||||||
|
# this source file
|
||||||
|
# keyed by $tmpfile so multiple destinations share a
|
||||||
|
# single decode task
|
||||||
if ! decodetaskid=$(
|
if ! decodetaskid=$(
|
||||||
Select tasks id <<<"key = $tmpfile"
|
Select tasks id <<<"key = $tmpfile"
|
||||||
)
|
)
|
||||||
@ -160,11 +166,18 @@ decodeFile() {
|
|||||||
fi
|
fi
|
||||||
if (( sox_needed ))
|
if (( sox_needed ))
|
||||||
then
|
then
|
||||||
|
# Insert a sox post-processing task chained
|
||||||
|
# after the decode task
|
||||||
decodeSox "$tempdir/$tmpfile.wav"
|
decodeSox "$tempdir/$tmpfile.wav"
|
||||||
if ! soxtaskid=$(
|
if ! soxtaskid=$(
|
||||||
Select tasks id <<<"key = $tmpfile"
|
Select tasks id <<<"key = $tmpfile"
|
||||||
)
|
)
|
||||||
then
|
then
|
||||||
|
# Increment the decode task's
|
||||||
|
# required_by counter so cleaner()
|
||||||
|
# waits for all dependent tasks to
|
||||||
|
# finish before cleaning up the
|
||||||
|
# intermediate file
|
||||||
parent_required=$(
|
parent_required=$(
|
||||||
Select tasks required_by \
|
Select tasks required_by \
|
||||||
<<<"id = $decodetaskid"
|
<<<"id = $decodetaskid"
|
||||||
|
|||||||
@ -1,6 +1,26 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
decodeMpcdec() {
|
decodeMpcdec() {
|
||||||
|
# Set the tmpfile base name for this specific decode task
|
||||||
|
# source file id + decoder name
|
||||||
tmpfile="${fileid}mpcdec"
|
tmpfile="${fileid}mpcdec"
|
||||||
|
# Build mpcdec command: decode Musepack to WAV in tempdir
|
||||||
|
# ${ionice} prepends the ionice invocation string if configured
|
||||||
commandline=(${ionice}mpcdec)
|
commandline=(${ionice}mpcdec)
|
||||||
|
# Encode any literal newlines in the filename as the SQL-safe inline
|
||||||
|
# marker
|
||||||
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}" "$tempdir/$tmpfile.wav")
|
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}" "$tempdir/$tmpfile.wav")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,26 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
decodeOpusdec() {
|
decodeOpusdec() {
|
||||||
|
# Set the tmpfile base name for this specific decode task
|
||||||
|
# source file id + decoder name
|
||||||
tmpfile="${fileid}opusdec"
|
tmpfile="${fileid}opusdec"
|
||||||
|
# Build opusdec command: decode Opus to WAV in tempdir
|
||||||
|
# ${ionice} prepends the ionice invocation string if configured
|
||||||
commandline=(${ionice}opusdec)
|
commandline=(${ionice}opusdec)
|
||||||
|
# Encode any literal newlines in the filename as the SQL-safe inline
|
||||||
|
# marker
|
||||||
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}" "$tempdir/$tmpfile.wav")
|
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}" "$tempdir/$tmpfile.wav")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,36 +1,67 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
decodeSox() {
|
decodeSox() {
|
||||||
|
# Build a SoX decode command with optional processing (normalize,
|
||||||
|
# resample, up/downmix)
|
||||||
commandline=(${ionice}sox --single-threaded --temp "$tempdir")
|
commandline=(${ionice}sox --single-threaded --temp "$tempdir")
|
||||||
soxoptions_in=''
|
soxoptions_in=''
|
||||||
soxoptions_out=''
|
soxoptions_out=''
|
||||||
|
|
||||||
|
# Add --norm if output normalization is requested
|
||||||
if (( ${destinationnormalize["$destination"]} ))
|
if (( ${destinationnormalize["$destination"]} ))
|
||||||
then
|
then
|
||||||
commandline+=(--norm)
|
commandline+=(--norm)
|
||||||
soxoptions_in+=' --norm'
|
soxoptions_in+=' --norm'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# $1 can be set to pass an already decoded file.
|
||||||
|
# Use the the original file when unset
|
||||||
if [ -n "$1" ]
|
if [ -n "$1" ]
|
||||||
then
|
then
|
||||||
commandline+=("$1")
|
commandline+=("$1")
|
||||||
else
|
else
|
||||||
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}")
|
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Add resampling if requested
|
||||||
if [ -n "${destinationfrequency["$destination"]}" ] \
|
if [ -n "${destinationfrequency["$destination"]}" ] \
|
||||||
&& (( ${rate:-0} != ${destinationfrequency["$destination"]} ))
|
&& (( ${rate:-0} != ${destinationfrequency["$destination"]} ))
|
||||||
then
|
then
|
||||||
commandline+=(-r ${destinationfrequency["$destination"]})
|
commandline+=(-r ${destinationfrequency["$destination"]})
|
||||||
soxoptions_out+=" -r ${destinationfrequency["$destination"]}"
|
soxoptions_out+=" -r ${destinationfrequency["$destination"]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Add channel up/downmixing if requested
|
||||||
if [ -n "${destinationchannels["$destination"]}" ] \
|
if [ -n "${destinationchannels["$destination"]}" ] \
|
||||||
&& (( ${channels:-0} != ${destinationchannels["$destination"]} ))
|
&& (( ${channels:-0} != ${destinationchannels["$destination"]} ))
|
||||||
then
|
then
|
||||||
commandline+=(-c ${destinationchannels["$destination"]})
|
commandline+=(-c ${destinationchannels["$destination"]})
|
||||||
soxoptions_out+=" -c ${destinationchannels["$destination"]}"
|
soxoptions_out+=" -c ${destinationchannels["$destination"]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Downsample to 16-bit if source resolution exceeds 16 bits
|
||||||
if (( ${depth:-0} > 16 ))
|
if (( ${depth:-0} > 16 ))
|
||||||
then
|
then
|
||||||
commandline+=(-b 16)
|
commandline+=(-b 16)
|
||||||
soxoptions_out+=" -b 16"
|
soxoptions_out+=" -b 16"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Encode all sox options into the tmpfile name so different processing
|
||||||
|
# chains get unique WAV files
|
||||||
|
# Avoids conflicts with different samplerate/norm/channel counts
|
||||||
tmpfile="$fileid${soxoptions_in// /}${soxoptions_out// /}"
|
tmpfile="$fileid${soxoptions_in// /}${soxoptions_out// /}"
|
||||||
commandline+=("$tempdir/$tmpfile.wav")
|
commandline+=("$tempdir/$tmpfile.wav")
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user