sane-sync-music: target opus instead of mp3 when transcoding
opus supports surround sound
This commit is contained in:
@@ -75,6 +75,10 @@ IGNORE = [
|
|||||||
'.nsf_', #< "NES Sound File"
|
'.nsf_', #< "NES Sound File"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# mp3 doesn't support surround sound (by default).
|
||||||
|
# opus supports at least 5.1 and 7.1
|
||||||
|
PREFERRED_LOSSY_FMT = '.opus'
|
||||||
|
|
||||||
def approx_eq(a: float, b: float, threshold: float) -> bool:
|
def approx_eq(a: float, b: float, threshold: float) -> bool:
|
||||||
return abs(b - a) <= threshold
|
return abs(b - a) <= threshold
|
||||||
|
|
||||||
@@ -137,7 +141,7 @@ class TranscodePreferences:
|
|||||||
if input_ext in LOSSY_FMTS:
|
if input_ext in LOSSY_FMTS:
|
||||||
return input_ext
|
return input_ext
|
||||||
else:
|
else:
|
||||||
return ".mp3"
|
return PREFERRED_LOSSY_FMT
|
||||||
|
|
||||||
def get_compat_audio_output(self, input_ext: str) -> str:
|
def get_compat_audio_output(self, input_ext: str) -> str:
|
||||||
if input_ext in COMPAT_AUDIO_FMTS:
|
if input_ext in COMPAT_AUDIO_FMTS:
|
||||||
@@ -145,7 +149,7 @@ class TranscodePreferences:
|
|||||||
elif input_ext in LOSSLESS_FMTS:
|
elif input_ext in LOSSLESS_FMTS:
|
||||||
return ".flac"
|
return ".flac"
|
||||||
else:
|
else:
|
||||||
return ".mp3"
|
return PREFERRED_LOSSY_FMT
|
||||||
|
|
||||||
|
|
||||||
class Encoder:
|
class Encoder:
|
||||||
@@ -191,9 +195,34 @@ class Encoder:
|
|||||||
self.destructive(None, os.remove, path)
|
self.destructive(None, os.remove, path)
|
||||||
|
|
||||||
def convert(self, source: Path, dest: Path, target_samplerate: int | None) -> None:
|
def convert(self, source: Path, dest: Path, target_samplerate: int | None) -> None:
|
||||||
assert dest.suffix == '.mp3', "conversion to a target other than mp3 not yet supported"
|
|
||||||
logger.info(f'converting {source} -> {dest}')
|
logger.info(f'converting {source} -> {dest}')
|
||||||
|
|
||||||
|
codec_flags = []
|
||||||
|
if dest.suffix == '.mp3':
|
||||||
|
codec_flags = [
|
||||||
|
'-codec:a', 'libmp3lame',
|
||||||
|
'-qscale:a', '0', # VBR0
|
||||||
|
]
|
||||||
|
elif dest.suffix == '.opus':
|
||||||
|
codec_flags = [
|
||||||
|
'-codec:a', 'libopus',
|
||||||
|
# opus defaults to 96 kbps for stereo (which is not enough IMO). 300-something for 5.1.
|
||||||
|
# no easy way to specify behavior which scales here AFAICT, so ... ?
|
||||||
|
# recs: <https://wiki.xiph.org/Opus_Recommended_Settings>
|
||||||
|
'-b:a', '192000',
|
||||||
|
]
|
||||||
|
if target_samplerate is not None:
|
||||||
|
# opus doesn't support 44.1 kHz, so use 48kHz instead.
|
||||||
|
# not sure about the other bitrates: these are speculative.
|
||||||
|
if target_samplerate > 96000:
|
||||||
|
target_samplerate = 192000
|
||||||
|
elif target_samplerate > 48000:
|
||||||
|
target_samplerate = 96000
|
||||||
|
else:
|
||||||
|
target_samplerate = 48000
|
||||||
|
else:
|
||||||
|
assert False, f'conversion to {dest.suffix} not yet supported'
|
||||||
|
|
||||||
samplerate_flags = ['-ar', str(target_samplerate)] if target_samplerate else []
|
samplerate_flags = ['-ar', str(target_samplerate)] if target_samplerate else []
|
||||||
|
|
||||||
self.check_output([
|
self.check_output([
|
||||||
@@ -202,9 +231,9 @@ class Encoder:
|
|||||||
'-y', # force overwrite
|
'-y', # force overwrite
|
||||||
'-i', str(source),
|
'-i', str(source),
|
||||||
'-codec:v', 'copy',
|
'-codec:v', 'copy',
|
||||||
'-codec:a', 'libmp3lame',
|
] + codec_flags + samplerate_flags + [
|
||||||
'-qscale:a', '0'
|
str(dest)
|
||||||
] + samplerate_flags + [str(dest)])
|
])
|
||||||
|
|
||||||
def cp_or_convert(self, source: Path, dest: Path) -> None:
|
def cp_or_convert(self, source: Path, dest: Path) -> None:
|
||||||
source_samplerate = None
|
source_samplerate = None
|
||||||
|
Reference in New Issue
Block a user