Skip to content

Commit 9f4ea0f

Browse files
committed
Change mimetypes usage to a hardcoded list of supported FFmpeg audio ext
mimetypes list is incomplete and even if using the user's system's list, might still not recognize the audio files correctly. This way, if the extension is not one of the supported FFmpeg extensions, we hope the user knows what they're doing and are using an audio file that FFmpeg can decode, and simply re-encode losslessly to WAV.
1 parent 240ab21 commit 9f4ea0f

2 files changed

Lines changed: 48 additions & 24 deletions

File tree

acsuite/__init__.py

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
"""Frame-based cutting/trimming/splicing of audio with VapourSynth."""
1+
"""Frame-based cutting/trimming/splicing of audio with VapourSynth and FFmpeg."""
22
__all__ = ['eztrim']
33
__author__ = 'Dave <orangechannel@pm.me>'
4-
__date__ = '26 July 2020'
4+
__date__ = '29 July 2020'
55
__credits__ = """AzraelNewtype, for the original audiocutter.py.
66
Ricardo Constantino (wiiaboo), for vfr.py from which this was inspired.
77
doop, for explaining the use of None for empty slicing
88
"""
9-
__version__ = '5.0.0'
9+
__version__ = '5.0.1'
1010

1111
import fractions
12-
import mimetypes
1312
import os
1413
import pathlib
1514
import subprocess
@@ -65,6 +64,8 @@ def eztrim(clip: vs.VideoNode,
6564
``src[15]`` must be entered as ``trims=(15, 16)``.
6665
:param audio_file: A string or path-like object refering to the source audio file's location
6766
(i.e. '/path/to/audio_file.ext').
67+
If the extension is not recognized as a valid audio file extension for FFmpeg's encoders,
68+
the audio will be re-encoded to WAV losslessly.
6869
:param outfile: Either a filename 'out.ext' or a full path '/path/to/out.ext'
6970
that will be used for the trimmed audio file.
7071
The extension will be automatically inserted for you,
@@ -82,17 +83,40 @@ def eztrim(clip: vs.VideoNode,
8283
else:
8384
if not os.path.isfile(audio_file):
8485
raise FileNotFoundError(f"eztrim: {audio_file} not found")
85-
if not mimetypes.types_map[os.path.splitext(audio_file)[-1]].startswith('audio/'):
86-
raise ValueError(f"{audio_file} does not seem to be an audio file; "
87-
f"try to extract the audio track first if it is in a container")
86+
87+
audio_file_name, audio_file_ext = os.path.splitext(audio_file)
88+
ffmpeg_valid_encoder_extensions = {
89+
'.aac', '.m4a', '.adts',
90+
'.ac3',
91+
'.alac', '.caf',
92+
'.dca', '.dts',
93+
'.eac3',
94+
'.flac',
95+
'.gsm',
96+
'.mlp',
97+
'.mp2', '.mp3', '.mpga',
98+
'.opus', '.spx', '.ogg', '.oga'
99+
'.pcm', '.raw',
100+
'.sbc',
101+
'.thd',
102+
'.tta',
103+
'.wav',
104+
'.wma',
105+
}
106+
if audio_file_ext not in ffmpeg_valid_encoder_extensions:
107+
warn(f"{audio_file_ext} is not a supported extension by FFmpeg's audio encoders, re-encoding to WAV", Warning)
108+
audio_file_ext = '.wav'
109+
else:
110+
codec_args = ['-c:a', 'copy']
88111

89112
if outfile is None:
90-
outfile = os.path.splitext(audio_file)[0] + '_cut' + os.path.splitext(audio_file)[-1]
113+
outfile = audio_file_name + '_cut' + audio_file_ext
91114
elif not os.path.splitext(outfile)[1]:
92-
outfile += os.path.splitext(audio_file)[-1]
93-
elif os.path.splitext(audio_file)[-1] != os.path.splitext(outfile)[-1]:
94-
outfile = os.path.splitext(outfile)[0] + os.path.splitext(audio_file)[-1]
95-
elif os.path.isfile(outfile):
115+
outfile += audio_file_ext
116+
elif os.path.splitext(outfile)[-1] != audio_file_ext:
117+
outfile = os.path.splitext(outfile)[0] + audio_file_ext
118+
119+
if os.path.isfile(outfile):
96120
raise FileExistsError(f"eztrim: {outfile} already exists")
97121

98122
if ffmpeg_path is None:
@@ -103,7 +127,7 @@ def eztrim(clip: vs.VideoNode,
103127
try:
104128
args = ['ffmpeg', '-version']
105129
if subprocess.run(args, stdout=subprocess.PIPE, text=True).stdout.split()[0] != 'ffmpeg':
106-
raise FileNotFoundError("ffmpeg executable not working properly")
130+
raise ValueError("ffmpeg executable not working properly")
107131
except FileNotFoundError:
108132
raise FileNotFoundError("ffmpeg executable not found in PATH") from None
109133

@@ -156,28 +180,28 @@ def eztrim(clip: vs.VideoNode,
156180
ffmpeg_silence = [str(ffmpeg_path), '-hide_banner', '-loglevel', '16'] if quiet else [str(ffmpeg_path), '-hide_banner']
157181

158182
if len(cut_ts_s) == 1:
159-
args = ffmpeg_silence + ['-i', audio_file, '-vn', '-ss', cut_ts_s[0], '-to', cut_ts_e[0], '-c:a', 'copy', outfile]
183+
args = ffmpeg_silence + ['-i', audio_file, '-vn', '-ss', cut_ts_s[0], '-to', cut_ts_e[0]] + codec_args + [outfile]
160184
run(args)
161185
return
162186

163187
times = [[s, e] for s, e in zip(cut_ts_s, cut_ts_e)]
164-
if os.path.isfile('_temp_concat.txt'):
165-
raise ValueError("_temp_concat.txt already exists, quitting")
188+
if os.path.isfile('_acsuite_temp_concat.txt'):
189+
raise ValueError("_acsuite_temp_concat.txt already exists, quitting")
166190
else:
167-
concat_file = open('_temp_concat.txt', 'w')
191+
concat_file = open('_acsuite_temp_concat.txt', 'w')
168192
temp_filelist = []
169193
for key, time in enumerate(times):
170-
outfile_tmp = f'_temp_output_{key}' + os.path.splitext(outfile)[-1]
194+
outfile_tmp = f'_acsuite_temp_output_{key}' + os.path.splitext(outfile)[-1]
171195
concat_file.write(f"file {outfile_tmp}\n")
172196
temp_filelist.append(outfile_tmp)
173-
args = ffmpeg_silence + ['-i', audio_file, '-vn', '-ss', time[0], '-to', time[1], '-c:a', 'copy', outfile_tmp]
197+
args = ffmpeg_silence + ['-i', audio_file, '-vn', '-ss', time[0], '-to', time[1]] + codec_args + [outfile_tmp]
174198
run(args)
175199

176200
concat_file.close()
177-
args = ffmpeg_silence + ['-f', 'concat', '-i', '_temp_concat.txt', '-c', 'copy', outfile]
201+
args = ffmpeg_silence + ['-f', 'concat', '-i', '_acsuite_temp_concat.txt', '-c', 'copy', outfile]
178202
run(args)
179203

180-
os.remove('_temp_concat.txt')
204+
os.remove('_acsuite_temp_concat.txt')
181205
for file in temp_filelist:
182206
os.remove(file)
183207

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
setuptools.setup(
1010
name='acsuite-orangechannel',
11-
version='5.0.0',
12-
description='Frame-based cutting/trimming/splicing of audio with VapourSynth.',
11+
version='5.0.1',
12+
description='Frame-based cutting/trimming/splicing of audio with VapourSynth and FFmpeg.',
1313
long_description=long_description,
1414
long_description_content_type='text/markdown',
1515
url='https://github.com/OrangeChannel/acsuite',
@@ -26,7 +26,7 @@
2626
"Topic :: Multimedia :: Sound/Audio",
2727
"Typing :: Typed",
2828
],
29-
keywords="audio vapoursynth encoding trim cut",
29+
keywords="audio vapoursynth encoding trim cut ffmpeg",
3030
project_urls={
3131
'Documentation': 'https://orangechannel.github.io/acsuite/html/index.html',
3232
'Source': 'https://github.com/OrangeChannel/acsuite/blob/master/acsuite/__init__.py',

0 commit comments

Comments
 (0)