Spaces:
Runtime error
Runtime error
first
Browse files- .vscode/settings.json +39 -0
- app.py +140 -0
- gitignore +25 -0
- requirements.txt +3 -0
.vscode/settings.json
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"editor.trimAutoWhitespace": true,
|
3 |
+
"files.trimTrailingWhitespace": true, // 儲存的時候,會幫你自動過濾多餘的空格
|
4 |
+
"files.autoSave": "onFocusChange", // 是否自動儲存檔案
|
5 |
+
"editor.formatOnSave": true,
|
6 |
+
// "editor.defaultFormatter": "esbenp.prettier-vscode",
|
7 |
+
// "[javascriptreact]": {
|
8 |
+
// "editor.defaultFormatter": "esbenp.prettier-vscode",
|
9 |
+
// "editor.formatOnPaste": false, //Black didn;t support format selection
|
10 |
+
// "editor.formatOnSave": true,
|
11 |
+
// "editor.insertSpaces": true,
|
12 |
+
// "editor.detectIndentation": true,
|
13 |
+
// "editor.tabSize": 2
|
14 |
+
// },
|
15 |
+
"editor.wordWrapColumn": 240,
|
16 |
+
"python.linting.enabled": false,
|
17 |
+
"python.linting.pylintEnabled": true,
|
18 |
+
"python.linting.pylintPath": "pylint",
|
19 |
+
"python.linting.pylintArgs": [
|
20 |
+
"--max-line-length",
|
21 |
+
"240",
|
22 |
+
"--aggressive"
|
23 |
+
],
|
24 |
+
// "python.formatting.provider": "black", // or "black" here
|
25 |
+
// "python.formatting.blackArgs": [
|
26 |
+
// "--line-length",
|
27 |
+
// "80"
|
28 |
+
// ],
|
29 |
+
"[python]": {
|
30 |
+
// 加入這幾行
|
31 |
+
"editor.formatOnPaste": false, //Black didn;t support format selection
|
32 |
+
"editor.formatOnSave": true,
|
33 |
+
// "editor.renderIndentGuides": true,
|
34 |
+
"editor.insertSpaces": true,
|
35 |
+
"editor.detectIndentation": true,
|
36 |
+
"editor.tabSize": 4
|
37 |
+
},
|
38 |
+
// "python.analysis.typeCheckingMode": "basic",
|
39 |
+
}
|
app.py
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import openai
|
3 |
+
from typing import Iterator, TextIO
|
4 |
+
import tempfile
|
5 |
+
from pydub import AudioSegment
|
6 |
+
|
7 |
+
|
8 |
+
def audio_from_file(filename: str) -> AudioSegment:
|
9 |
+
try:
|
10 |
+
audio = AudioSegment.from_file(filename)
|
11 |
+
except FileNotFoundError:
|
12 |
+
raise ValueError(
|
13 |
+
f"Cannot load audio from file: `{filename}` not found. Do you forgot to install `ffmpeg`."
|
14 |
+
)
|
15 |
+
|
16 |
+
return audio
|
17 |
+
|
18 |
+
|
19 |
+
def format_timestamp(seconds: float, always_include_hours: bool = False):
|
20 |
+
assert seconds >= 0, "non-negative timestamp expected"
|
21 |
+
milliseconds = round(seconds * 1000.0)
|
22 |
+
|
23 |
+
hours = milliseconds // 3_600_000
|
24 |
+
milliseconds -= hours * 3_600_000
|
25 |
+
|
26 |
+
minutes = milliseconds // 60_000
|
27 |
+
milliseconds -= minutes * 60_000
|
28 |
+
|
29 |
+
seconds = milliseconds // 1_000
|
30 |
+
milliseconds -= seconds * 1_000
|
31 |
+
|
32 |
+
hours_marker = f"{hours}:" if always_include_hours or hours > 0 else ""
|
33 |
+
return f"{hours_marker}{minutes:02d}:{seconds:02d}.{milliseconds:03d}"
|
34 |
+
|
35 |
+
|
36 |
+
def write_srt(transcript: Iterator[dict], file: TextIO):
|
37 |
+
"""
|
38 |
+
Write a transcript to a file in SRT format.
|
39 |
+
Example usage:
|
40 |
+
from pathlib import Path
|
41 |
+
from whisper.utils import write_srt
|
42 |
+
result = transcribe(model, audio_path, temperature=temperature, **args)
|
43 |
+
# save SRT
|
44 |
+
audio_basename = Path(audio_path).stem
|
45 |
+
with open(Path(output_dir) / (audio_basename + ".srt"), "w", encoding="utf-8") as srt:
|
46 |
+
write_srt(result["segments"], file=srt)
|
47 |
+
"""
|
48 |
+
with open(file, "w", encoding="UTF-8") as f:
|
49 |
+
for segment in transcript:
|
50 |
+
# write srt lines
|
51 |
+
id = segment["id"]
|
52 |
+
start = format_timestamp(segment["start"], always_include_hours=True)
|
53 |
+
end = format_timestamp(segment["end"], always_include_hours=True)
|
54 |
+
text = segment["text"].strip().replace("-->", "->")
|
55 |
+
|
56 |
+
f.write(f"{id}\n{start} --> {end}\n{text}\n\n")
|
57 |
+
|
58 |
+
|
59 |
+
def create_main_tab():
|
60 |
+
with gr.Blocks() as demo:
|
61 |
+
with gr.Row():
|
62 |
+
with gr.Column():
|
63 |
+
api_text = gr.Textbox(label="OpenAI API Key")
|
64 |
+
|
65 |
+
file_type = gr.Radio(
|
66 |
+
["Video", "Audio"],
|
67 |
+
value="Video",
|
68 |
+
label="File Type",
|
69 |
+
interactive=True,
|
70 |
+
)
|
71 |
+
video = gr.Video()
|
72 |
+
audio = gr.Audio(visible=False)
|
73 |
+
with gr.Row():
|
74 |
+
compress_btn = gr.Button("Compress")
|
75 |
+
submit_btn = gr.Button("Submit")
|
76 |
+
with gr.Column():
|
77 |
+
compress_file = gr.File(label="Compress file", interactive=False)
|
78 |
+
subtitle_file = gr.File(label="Subtitle")
|
79 |
+
message_text = gr.Textbox(label="Info")
|
80 |
+
|
81 |
+
def handle_file_type_change(evt: gr.SelectData):
|
82 |
+
if evt.index == 0:
|
83 |
+
# Video
|
84 |
+
return [gr.update(visible=True), gr.update(visible=False)]
|
85 |
+
elif evt.index == 1:
|
86 |
+
# Audio
|
87 |
+
return [gr.update(visible=False), gr.update(visible=True)]
|
88 |
+
|
89 |
+
file_type.select(
|
90 |
+
handle_file_type_change,
|
91 |
+
None,
|
92 |
+
[video, audio],
|
93 |
+
)
|
94 |
+
|
95 |
+
def handle_compress_btn_submit(file_type, video, audio):
|
96 |
+
if file_type == "Video":
|
97 |
+
audio_data = audio_from_file(video)
|
98 |
+
elif file_type == "Audio":
|
99 |
+
audio_data = audio_from_file(audio)
|
100 |
+
|
101 |
+
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmp_file:
|
102 |
+
audio_data.export(tmp_file.name, format="mp3", bitrate="96k")
|
103 |
+
|
104 |
+
return tmp_file.name
|
105 |
+
|
106 |
+
compress_btn.click(
|
107 |
+
fn=handle_compress_btn_submit,
|
108 |
+
inputs=[file_type, video, audio],
|
109 |
+
outputs=[compress_file],
|
110 |
+
)
|
111 |
+
|
112 |
+
def handle_btn_submit(compress_file, api_text):
|
113 |
+
def transcribe_audio(input_file, output_file):
|
114 |
+
with open(input_file, "rb") as f:
|
115 |
+
try:
|
116 |
+
result = openai.Audio.transcribe("whisper-1", f)
|
117 |
+
write_srt(result["segments"], output_file)
|
118 |
+
return "Success! The subtitle file will be named: {output_file}"
|
119 |
+
except Exception as e:
|
120 |
+
return f"Error. OpenAI API unavailable. Received: {e}"
|
121 |
+
|
122 |
+
openai.api_key = api_text
|
123 |
+
|
124 |
+
with tempfile.NamedTemporaryFile(suffix=".srt", delete=False) as out_file:
|
125 |
+
out_message = transcribe_audio(compress_file.name, out_file.name)
|
126 |
+
|
127 |
+
return out_file.name, out_message
|
128 |
+
|
129 |
+
submit_btn.click(
|
130 |
+
fn=handle_btn_submit,
|
131 |
+
inputs=[compress_file, api_text],
|
132 |
+
outputs=[subtitle_file, message_text],
|
133 |
+
)
|
134 |
+
|
135 |
+
return demo
|
136 |
+
|
137 |
+
|
138 |
+
demo = create_main_tab()
|
139 |
+
if __name__ == "__main__":
|
140 |
+
demo.launch()
|
gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
.vscode/
|
3 |
+
build/
|
4 |
+
dist/
|
5 |
+
dist_onefile/
|
6 |
+
flagged/
|
7 |
+
|
8 |
+
venv/
|
9 |
+
|
10 |
+
test/
|
11 |
+
img/
|
12 |
+
mp4/
|
13 |
+
out/
|
14 |
+
wav/
|
15 |
+
tmp/
|
16 |
+
project/
|
17 |
+
repositories/
|
18 |
+
|
19 |
+
__pycache__/
|
20 |
+
pretrained_models/
|
21 |
+
|
22 |
+
# *.srt
|
23 |
+
|
24 |
+
test.py
|
25 |
+
**/.openai
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
openai
|
3 |
+
pydub
|