-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathmain.py
167 lines (150 loc) · 5.18 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import click
from loguru import logger
from whisper import _MODELS
from whisper.tokenizer import LANGUAGES
from config import OUTPUT_DIR, WHISPER_MODEL
from core.audio import generate_audio, generate_subtitle, generate_vtt
from core.downloader import download
from core.video import generate_video
WHISPER_SUPPORT_TYPES = ["vtt", "srt", "json", "txt", "tsv", "all"]
OPENAI_API_SUPPORT_TYPES = ["json", "text", "vtt", "srt"]
class Mutex(click.Option):
def __init__(self, *args, **kwargs):
self.not_required_if: list = kwargs.pop("not_required_if", [])
assert self.not_required_if, "'not_required_if' parameter required"
kwargs["help"] = (
kwargs.get("help", "")
+ ". Notice: this option is mutually exclusive with "
+ ", ".join(self.not_required_if)
+ "."
).strip()
super(Mutex, self).__init__(*args, **kwargs)
def handle_parse_result(self, ctx, opts, args):
current_opt: bool = self.name in opts
for mutex_opt in self.not_required_if:
if mutex_opt in opts:
if current_opt:
raise click.UsageError(
"Illegal usage: '"
+ str(self.name)
+ "' is mutually exclusive with "
+ str(mutex_opt)
+ "."
)
else:
self.prompt = None
if current_opt and not opts[self.name]:
raise click.UsageError(
f"Illegal usage: The value of '{self.name}' cannot be empty."
)
return super(Mutex, self).handle_parse_result(ctx, opts, args)
@click.group()
def cli():
"""`vt` is a tool for adding subtitle to videos and generating videos in other languages."""
@cli.command()
@click.option("-p", "--path", required=True, help="Local file path or video url.")
@click.option("-o", "--output", default=OUTPUT_DIR, help="Generated video dir.")
@click.option(
"-l",
"--language",
default="en",
type=click.Choice(LANGUAGES.keys(), case_sensitive=False),
help="Subtitle language.",
)
@click.option(
"-m",
"--model",
default=WHISPER_MODEL,
type=click.Choice(_MODELS.keys(), case_sensitive=False),
help="Whisper model name.",
)
@click.option(
"-m",
"--method",
default="whisper",
type=click.Choice(["whisper", "openai_api"], case_sensitive=False),
help="Method for generating subtitle files.",
)
@click.option(
"-f",
"--format",
default="vtt",
help="Subtitle format.",
)
def subtitle(path, output, language, model, method, format):
if method == "whisper" and format not in WHISPER_SUPPORT_TYPES:
raise click.UsageError(
f"Illegal usage: `whisper` method only support: {WHISPER_SUPPORT_TYPES}."
)
elif method == "openai_api" and format not in OPENAI_API_SUPPORT_TYPES:
raise click.UsageError(
f"Illegal usage: `openai_api` method only support: {OPENAI_API_SUPPORT_TYPES}."
)
if path.startswith("http"):
media = download(path)
audio = media.audio
else:
audio = generate_audio(path)
generate_subtitle(audio, method, language, format, output, model_name=model)
@cli.command()
@click.option("-p", "--path", required=True, help="Local file path.")
@click.option("-o", "--output", default=OUTPUT_DIR, help="Generated video dir.")
@click.option(
"-b",
"--bilingual",
default="",
cls=Mutex,
not_required_if=["subtitles"],
help="Use bilingual subtitle. you can specify the subtitle language by `--subtitles`",
)
@click.option(
"-s",
"--subtitles",
default="",
cls=Mutex,
not_required_if=["bilingual"],
help='Subtitle languages. split by ","',
)
def local(path, output, bilingual, subtitles):
if bilingual and "," not in bilingual:
raise click.UsageError(
"Illegal usage: `--bilingual` requires 2 language subtitles, you can use `cn,en` or `en,cn`"
)
audio = generate_audio(path)
vtts = generate_vtt(audio, bilingual, subtitles)
if not vtts:
logger.warning("No subtitles generated.")
for video in generate_video(path, vtts, output):
logger.info(f"Generated: {video}")
@cli.command()
@click.option("-u", "--url", required=True, help="Video url.")
@click.option("-o", "--output", default=OUTPUT_DIR, help="Generated video dir.")
@click.option(
"-b",
"--bilingual",
default="",
cls=Mutex,
not_required_if=["subtitles"],
help="Use bilingual subtitle",
)
@click.option(
"-s",
"--subtitles",
default="zh,en",
cls=Mutex,
not_required_if=["bilingual"],
help='Subtitle languages. split by ","',
)
def web(url, output, bilingual, subtitles):
if bilingual and "," not in bilingual:
raise click.UsageError(
"Illegal usage: `--bilingual` requires 2 language subtitles, you can use `cn,en` or `en,cn`"
)
media = download(url)
vtts = generate_vtt(media.audio, bilingual, subtitles)
if not vtts:
logger.warning("No subtitles generated.")
for video in generate_video(media.video, vtts, output):
logger.info(f"Generated: {video}")
if __name__ == "__main__":
cli()