Skip to content

Commit 33fe2bc

Browse files
Merge pull request #39 from yash-fn/master
Dry-run + ability to specify models + minor edits
2 parents 97fb14d + ab0a71d commit 33fe2bc

File tree

4 files changed

+132
-40
lines changed

4 files changed

+132
-40
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ In the age of OTT platforms, there are still some who prefer to download movies/
7777
* For a GPU build that is reusable (saving time on instantiating the program):
7878
```bash
7979
$ docker build --build-arg BASEIMAGE=nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04 --build-arg DEPSLIST=requirements-gpu.txt -t autosub-base . && \
80-
docker run --gpus all --name autosub-base autosub-base || \
81-
docker commit autosub-base autosub-instance
80+
docker run --gpus all --name autosub-base autosub-base --dry-run || \
81+
docker commit --change 'CMD []' autosub-base autosub-instance
8282
```
8383
* Then
8484
```bash

autosub/audioProcessing.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import sys
55
import subprocess
66
import numpy as np
7-
7+
from os.path import basename
88

99
def extract_audio(input_file, audio_file_name):
1010
"""Extract audio from input video file and save to audio/ in root dir
@@ -17,8 +17,8 @@ def extract_audio(input_file, audio_file_name):
1717
try:
1818
command = ["ffmpeg", "-hide_banner", "-loglevel", "warning", "-i", input_file, "-ac", "1", "-ar", "16000",
1919
"-vn", "-f", "wav", audio_file_name]
20-
ret = subprocess.call(command)
21-
print("Extracted audio to audio/{}".format(audio_file_name.split("/")[-1]))
20+
ret = subprocess.run(command).returncode
21+
print("Extracted audio to audio/{}".format(basename(audio_file_name)))
2222
except Exception as e:
2323
print("Error: ", str(e))
2424
sys.exit(1)

autosub/main.py

+126-34
Original file line numberDiff line numberDiff line change
@@ -107,52 +107,130 @@ def ds_process_audio(ds, audio_file, output_file_handle_dict, split_duration):
107107
def main():
108108
global line_count
109109
print("AutoSub\n")
110-
111-
for x in os.listdir():
112-
if x.endswith(".pbmm"):
113-
print("Model: ", os.path.join(os.getcwd(), x))
114-
ds_model = os.path.join(os.getcwd(), x)
115-
if x.endswith(".scorer"):
116-
print("Scorer: ", os.path.join(os.getcwd(), x))
117-
ds_scorer = os.path.join(os.getcwd(), x)
118-
119-
# Load DeepSpeech model
120-
try:
121-
ds = Model(ds_model)
122-
except:
123-
print("Invalid model file. Exiting\n")
124-
sys.exit(1)
125-
126-
try:
127-
ds.enableExternalScorer(ds_scorer)
128-
except:
129-
print("Invalid scorer file. Running inference using only model file\n")
130-
110+
111+
#Parsing Arguments Section
131112
supported_output_formats = ['srt', 'vtt', 'txt']
132113
parser = argparse.ArgumentParser(description="AutoSub")
133-
parser.add_argument('--file', required=True,
134-
help='Input video file')
114+
115+
#Runtime Options
135116
parser.add_argument('--format', choices=supported_output_formats, nargs='+',
136117
help='Create only certain output formats rather than all formats',
137118
default=supported_output_formats)
138119
parser.add_argument('--split-duration', type=float,
139120
help='Split run-on sentences exceededing this duration (in seconds) into multiple subtitles',
140121
default=5)
141-
args = parser.parse_args()
122+
parser.add_argument('--dry-run', dest="dry_run", action="store_true",
123+
help="Perform dry-run to verify options prior to running. Also useful to instantiate cuda/tensorflow cache prior to running multiple times.")
142124

143-
if os.path.isfile(args.file):
144-
input_file = args.file
145-
print("\nInput file:", input_file)
125+
#Files that should be supplied
126+
#File no longer required here, but will check manually later
127+
#Basically EITHER file OR dry-run is sufficient
128+
parser.add_argument('--file', required=False,
129+
help='Input video file')
130+
parser.add_argument('--model', required=False,
131+
help='Input *.pbmm model file')
132+
parser.add_argument('--scorer', required=False,
133+
help='Input *.scorer file')
134+
135+
args = parser.parse_args()
136+
137+
#Please keep the following because I need it for verifying dockerfiles.
138+
print(sys.argv[0:])
139+
print("ARGS:", args)
140+
141+
def getmodel(args, arg_name):
142+
#prioritize supplied argument
143+
144+
if arg_name == 'model':
145+
arg_extension = '.pbmm'
146+
elif arg_name == 'scorer':
147+
arg_extension = '.scorer'
148+
else:
149+
print("Coding Error. This function only accepts model or scorer for arg_name.")
150+
sys.exit(1)
151+
152+
arg = args.__getattribute__(arg_name)
153+
154+
if arg is not None:
155+
model = os.path.abspath(arg)
156+
if not os.path.isfile(model):
157+
print(f"Error. Supplied file {arg} doesn't exist. Please supply a valid {arg_name} file via the --{arg_name} flag.")
158+
sys.exit(1)
159+
else:
160+
#try to find local models
161+
models_ = os.listdir()
162+
models = []
163+
for file in models_:
164+
if file.endswith(arg_extension):
165+
models.append(file)
166+
del(models_)
167+
168+
num_models = len(models)
169+
170+
if num_models == 0:
171+
print(f"Warning no {arg_name}s specified via --{arg_name} and none found in local directory. Please run getmodel.sh convenience script from autosub repo to get some.")
172+
if arg_name == 'model':
173+
print("Error: Must have pbmm model. Exiting")
174+
sys.exit(1)
175+
else:
176+
model = ''
177+
elif num_models != 1:
178+
print(f"Warning. Detected multiple *{arg_extension} files in local dir. You must specify which one you wish to use via the --{arg_name} field. Details: \n {num_models} {models}")
179+
if arg_name == 'model':
180+
print("Error: Must specify pbmm model. Exiting")
181+
sys.exit(1)
182+
else:
183+
print("Since I cannot know which scorer you wish to use, I just won't use any and try to run inference without it.")
184+
model = ''
185+
else:
186+
model = os.path.abspath(models[0])
187+
188+
print(f"{arg_name}: ", model)
189+
return(model)
190+
191+
def InstantiateModel(model, scorer):
192+
# Load DeepSpeech model
193+
try:
194+
ds = Model(model)
195+
except:
196+
print("Invalid model file. Exiting\n")
197+
sys.exit(1)
198+
199+
try:
200+
ds.enableExternalScorer(scorer)
201+
except:
202+
print("Invalid scorer file. Running inference using only model file\n")
203+
return(ds)
204+
205+
206+
ds_model = getmodel(args, 'model')
207+
ds_scorer = getmodel(args, 'scorer')
208+
209+
if args.dry_run:
210+
InstantiateModel(ds_model, ds_scorer)
211+
if args.file is not None:
212+
if not os.path.isfile(args.file):
213+
print(f"Error: {args.file}: No such file exists")
214+
sys.exit(0)
215+
216+
#Not a dry-run
217+
if args.file is not None:
218+
if os.path.isfile(args.file):
219+
input_file = args.file
220+
print("\nInput file:", input_file)
221+
else:
222+
print(args.file, ": No such file exists")
223+
sys.exit(1)
146224
else:
147-
print(args.file, ": No such file exists")
225+
print("Error. You must supply a file with --file or to instantiate cuda cache you must supply a --dry-run.")
148226
sys.exit(1)
149227

150228
base_directory = os.getcwd()
151229
output_directory = os.path.join(base_directory, "output")
152230
audio_directory = os.path.join(base_directory, "audio")
153231
video_prefix = os.path.splitext(os.path.basename(input_file))[0]
154232
audio_file_name = os.path.join(audio_directory, video_prefix + ".wav")
155-
233+
156234
output_file_handle_dict = {}
157235
for format in args.format:
158236
output_filename = os.path.join(output_directory, video_prefix + "." + format)
@@ -183,11 +261,25 @@ def main():
183261

184262
print("\nRunning inference:")
185263

186-
for filename in tqdm(sort_alphanumeric(os.listdir(audio_directory))):
187-
# Only run inference on relevant files, and don't run inference on the original audio file
188-
if filename.startswith(video_prefix) and (filename != os.path.basename(audio_file_name)):
189-
audio_segment_path = os.path.join(audio_directory, filename)
190-
ds_process_audio(ds, audio_segment_path, output_file_handle_dict, split_duration=args.split_duration)
264+
#Remove master audio file
265+
audiofiles=sort_alphanumeric(os.listdir(audio_directory))
266+
audiofiles.remove(os.path.basename(audio_file_name))
267+
268+
#Remove non related audiofiles potentially from other instances of autosub
269+
audiofiles_ = []
270+
for filename in audiofiles:
271+
if filename.startswith(video_prefix):
272+
audiofiles_.append(filename)
273+
audiofiles = audiofiles_
274+
del(audiofiles_)
275+
276+
#Process Segments
277+
278+
ds = InstantiateModel(ds_model, ds_scorer)
279+
280+
for filename in tqdm(audiofiles):
281+
audio_segment_path = os.path.join(audio_directory, filename)
282+
ds_process_audio(ds, audio_segment_path, output_file_handle_dict, split_duration=args.split_duration)
191283

192284
print("\n")
193285
for format in output_file_handle_dict:

scripts/gpu-build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
22
cd "$(dirname "$(readlink -f "$0")")"
33
cd ..
4-
docker build --build-arg BASEIMAGE=nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04 --build-arg DEPSLIST=requirements-gpu.txt -t autosub-base . && docker run --gpus all --name autosub-base autosub-base || docker commit autosub-base autosub-instance && docker container rm autosub-base
4+
docker build --build-arg BASEIMAGE=nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04 --build-arg DEPSLIST=requirements-gpu.txt -t autosub-base . && docker run --gpus all --name autosub-base autosub-base --dry-run && docker commit --change 'CMD []' autosub-base autosub-instance && docker container rm autosub-base
55

0 commit comments

Comments
 (0)