Spaces:
Sleeping
Sleeping
File size: 11,110 Bytes
63ecb0d d23f574 cf5f1c9 ae0ed1b 1e2d254 63ecb0d 144c78b 04ae3b4 63ecb0d 04ae3b4 4f95b2f 1e2d254 144c78b 63ecb0d 04ae3b4 144c78b 04ae3b4 63ecb0d 4f95b2f ae0ed1b 63ecb0d 4f95b2f 04ae3b4 4f95b2f 1e2d254 ae0ed1b 66791b6 e3825f8 63ecb0d 144c78b 63ecb0d 147a645 63ecb0d 144c78b 147a645 4f95b2f 144c78b 147a645 66791b6 144c78b 4f95b2f 04ae3b4 4f95b2f 144c78b 63ecb0d 144c78b 63ecb0d 4f95b2f ae0ed1b 1e2d254 ae0ed1b 04ae3b4 cf5f1c9 04ae3b4 cf5f1c9 ae0ed1b 04ae3b4 4f95b2f 04ae3b4 cf5f1c9 04ae3b4 cf5f1c9 6113bd9 cf5f1c9 5f10ef2 04ae3b4 cf5f1c9 5f10ef2 e3825f8 5f10ef2 b2ca465 5f10ef2 63ecb0d 144c78b 4f95b2f a33eef8 5a7c441 66791b6 cf5f1c9 66791b6 cf5f1c9 e3825f8 63ecb0d e3825f8 1e2d254 04ae3b4 ae0ed1b 7511df3 e3825f8 ae0ed1b 147a645 ae0ed1b cf5f1c9 ce7a58b e3825f8 ce7a58b e3825f8 ce7a58b e3825f8 ce7a58b e3825f8 1e2d254 ce7a58b e3825f8 1e2d254 e3825f8 63ecb0d e3825f8 144c78b 4f95b2f 144c78b |
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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
import openai
from pytube import YouTube
import argparse
import os
from tqdm import tqdm
from SRT import SRT_script
import stable_whisper
import time
parser = argparse.ArgumentParser()
parser.add_argument("--link", help="youtube video link here", default=None, type=str, required=False)
parser.add_argument("--video_file", help="local video path here", default=None, type=str, required=False)
parser.add_argument("--audio_file", help="local audio path here", default=None, type=str, required=False)
parser.add_argument("--srt_file", help="srt file input path here", default=None, type=str, required=False) # New argument
parser.add_argument("--download", help="download path", default='./downloads', type=str, required=False)
parser.add_argument("--output_dir", help="translate result path", default='./results', type=str, required=False)
parser.add_argument("--video_name", help="video name, if use video link as input, the name will auto-filled by youtube video name", default='placeholder', type=str, required=False)
parser.add_argument("--model_name", help="model name only support gpt-4 and gpt-3.5-turbo", type=str, required=False, default="gpt-3.5-turbo")
parser.add_argument("-only_srt", help="set script output to only .srt file", action='store_true')
parser.add_argument("-v", help="auto encode script with video", action='store_true')
args = parser.parse_args()
# input should be either video file or youtube video link.
if args.link is None and args.video_file is None and args.srt_file is None:
print("need video source or srt file")
exit()
# set up
openai.api_key = os.getenv("OPENAI_API_KEY")
DOWNLOAD_PATH = args.download
if not os.path.exists(DOWNLOAD_PATH):
os.mkdir(DOWNLOAD_PATH)
os.mkdir(f'{DOWNLOAD_PATH}/audio')
os.mkdir(f'{DOWNLOAD_PATH}/video')
RESULT_PATH = args.output_dir
if not os.path.exists(RESULT_PATH):
os.mkdir(RESULT_PATH)
# set video name as the input file name if not specified
if args.video_name == 'placeholder' :
# set video name to upload file name
if args.video_file is not None:
VIDEO_NAME = args.video_file.split('/')[-1].split('.')[0]
elif args.audio_file is not None:
VIDEO_NAME = args.audio_file.split('/')[-1].split('.')[0]
elif args.srt_file is not None:
VIDEO_NAME = args.srt_file.split('/')[-1].split('.')[0]
else:
VIDEO_NAME = args.video_name
model_name = args.model_name
threshold = 30
# get source audio
if args.link is not None and args.video_file is None:
# Download audio from YouTube
video_link = args.link
video = None
audio = None
try:
yt = YouTube(video_link)
video = yt.streams.filter(progressive=True, file_extension='mp4').order_by('resolution').desc().first()
if video:
video.download(f'{DOWNLOAD_PATH}/video')
print('Video download completed!')
else:
print("Error: Video stream not found")
audio = yt.streams.filter(only_audio=True, file_extension='mp4').first()
if audio:
audio.download(f'{DOWNLOAD_PATH}/audio')
print('Audio download completed!')
else:
print("Error: Audio stream not found")
except Exception as e:
print("Connection Error")
print(e)
exit()
video_path = f'{DOWNLOAD_PATH}/video/{video.default_filename}'
audio_path = '{}/audio/{}'.format(DOWNLOAD_PATH, audio.default_filename)
audio_file = open(audio_path, "rb")
if VIDEO_NAME == 'placeholder':
VIDEO_NAME = audio.default_filename.split('.')[0]
elif args.video_file is not None:
# Read from local
video_path = args.video_file
if args.audio_file is not None:
audio_file= open(args.audio_file, "rb")
audio_path = args.audio_file
else:
os.system(f'ffmpeg -i {args.video_file} -f mp3 -ab 192000 -vn {DOWNLOAD_PATH}/audio/{VIDEO_NAME}.mp3')
audio_file= open(f'{DOWNLOAD_PATH}/audio/{VIDEO_NAME}.mp3', "rb")
audio_path = f'{DOWNLOAD_PATH}/audio/{VIDEO_NAME}.mp3'
if not os.path.exists(f'{RESULT_PATH}/{VIDEO_NAME}'):
os.mkdir(f'{RESULT_PATH}/{VIDEO_NAME}')
if args.audio_file is not None:
audio_file= open(args.audio_file, "rb")
audio_path = args.audio_file
# Instead of using the script_en variable directly, we'll use script_input
srt_file_en = args.srt_file
if srt_file_en is not None:
srt = SRT_script.parse_from_srt_file(srt_file_en)
else:
# using whisper to perform speech-to-text and save it in <video name>_en.txt under RESULT PATH.
srt_file_en = "{}/{}/{}_en.srt".format(RESULT_PATH, VIDEO_NAME, VIDEO_NAME)
if not os.path.exists(srt_file_en):
# use OpenAI API for transcribe
# transcript = openai.Audio.transcribe("whisper-1", audio_file)
# use local whisper model
# model = whisper.load_model("base") # using base model in local machine (may use large model on our server)
# transcript = model.transcribe(audio_path)
# use stable-whisper
model = stable_whisper.load_model('base')
transcript = model.transcribe(audio_path, regroup = False)
(
transcript
.split_by_punctuation(['.', '。', '?'])
.merge_by_gap(.15, max_words=3)
.merge_by_punctuation([' '])
.split_by_punctuation(['.', '。', '?'])
)
# transcript.to_srt_vtt(srt_file_en)
transcript = transcript.to_dict()
srt = SRT_script(transcript['segments']) # read segments to SRT class
#Write SRT file
# from whisper.utils import WriteSRT
# with open(srt_file_en, 'w', encoding="utf-8") as f:
# writer = WriteSRT(RESULT_PATH)
# writer.write_result(transcript, f)
else:
srt = SRT_script.parse_from_srt_file(srt_file_en)
# srt class preprocess
srt.form_whole_sentence()
srt.spell_check_term()
srt.correct_with_force_term()
srt.write_srt_file_src(srt_file_en)
script_input = srt.get_source_only()
if not args.only_srt:
from srt2ass import srt2ass
assSub_en = srt2ass(srt_file_en, "default", "No", "Modest")
print('ASS subtitle saved as: ' + assSub_en)
# Split the video script by sentences and create chunks within the token limit
def script_split(script_in, chunk_size = 1000):
script_split = script_in.split('\n\n')
script_arr = []
range_arr = []
start = 1
end = 0
script = ""
for sentence in script_split:
if len(script) + len(sentence) + 1 <= chunk_size:
script += sentence + '\n\n'
end+=1
else:
range_arr.append((start, end))
start = end+1
end += 1
script_arr.append(script.strip())
script = sentence + '\n\n'
if script.strip():
script_arr.append(script.strip())
range_arr.append((start, len(script_split)-1))
assert len(script_arr) == len(range_arr)
return script_arr, range_arr
script_arr, range_arr = script_split(script_input)
# print(script_arr, range_arr)
# check whether previous translation is done
zh_file = "{}/{}/{}_zh.srt".format(RESULT_PATH, VIDEO_NAME, VIDEO_NAME)
segidx = 1
if os.path.exists(zh_file):
temp_file = "{}/{}/temp.srt".format(RESULT_PATH, VIDEO_NAME)
if os.path.exists(temp_file):
os.remove(temp_file)
with open(zh_file, "r") as f0:
for count, _ in enumerate(f0):
pass
count += 1
segidx = int(count/4)+1
with open("{}/{}/{}_en.srt".format(RESULT_PATH, VIDEO_NAME, VIDEO_NAME), "r") as f1, open(temp_file, "a") as f2:
x = f1.readlines()
#print(len(x))
if count >= len(x):
print('Work already done! Please delete {}_zh.srt files in result directory first in order to rework'.format(VIDEO_NAME))
exit()
for i, line in enumerate(x):
if i >= count:
#print(i)
f2.write(line)
srt = SRT_script.parse_from_srt_file(temp_file)
print('temp_contents')
print(srt.get_source_only())
def get_response(model_name, sentence):
if model_name == "gpt-3.5-turbo" or model_name == "gpt-4":
# print(s + "\n")
response = openai.ChatCompletion.create(
model=model_name,
messages = [
{"role": "system", "content": "You are a helpful assistant that translates English to Chinese and have decent background in starcraft2."},
{"role": "system", "content": "Your translation has to keep the orginal format and be as accurate as possible."},
{"role": "system", "content": "There is no need for you to add any comments or notes."},
{"role": "user", "content": 'Translate the following English text to Chinese: "{}"'.format(sentence)}
],
temperature=0.15
)
return response['choices'][0]['message']['content'].strip()
# if model_name == "text-davinci-003":
# prompt = f"Please help me translate this into Chinese:\n\n{s}\n\n"
# # print(prompt)
# response = openai.Completion.create(
# model=model_name,
# prompt=prompt,
# temperature=0.1,
# max_tokens=2000,
# top_p=1.0,
# frequency_penalty=0.0,
# presence_penalty=0.0
# )
# return response['choices'][0]['text'].strip()
pass
# Translate and save
for sentence, range in tqdm(zip(script_arr, range_arr)):
# using chatgpt model
print(f"now translating sentences {range}")
flag = True
while flag:
flag = False
try:
translate = get_response(model_name, sentence)
except Exception as e:
print("An error has occurred during translation:",e)
print("Retrying... the script will continue after 30 seconds.")
time.sleep(30)
flag = True
# add read-time output back and modify the post-processing by using one batch as an unit.
print(translate)
srt.set_translation(translate, range, model_name)
add_length = srt.check_len_and_split_range(range)
srt.realtime_write_srt(f"{RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_zh.srt",range, add_length,segidx)
srt.realtime_bilingual_write_srt(f"{RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_bi.srt",range, add_length,segidx)
# srt.check_len_and_split()
# srt.write_srt_file_translate(f"{RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_zh.srt")
# srt.write_srt_file_bilingual(f"{RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_bi.srt")
if not args.only_srt:
assSub_zh = srt2ass(f"{RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_zh.srt", "default", "No", "Modest")
print('ASS subtitle saved as: ' + assSub_zh)
if args.v:
if args.only_srt:
os.system(f'ffmpeg -i {video_path} -vf "subtitles={RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_zh.srt" {RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}.mp4')
else:
os.system(f'ffmpeg -i {video_path} -vf "subtitles={RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}_zh.ass" {RESULT_PATH}/{VIDEO_NAME}/{VIDEO_NAME}.mp4') |