-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtitler.py
164 lines (139 loc) · 7.32 KB
/
titler.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
import os
import subprocess
import requests
import sys
import colorama
from colorama import Fore, Style
from dotenv import load_dotenv
import openai
# Function to get all video files in a given directory
def get_video_files(directory):
video_files = []
for filename in os.listdir(directory):
if filename.endswith(".mp4"):
video_files.append(os.path.join(directory, filename))
return video_files
# Function to run vhisperx on a given video file
def run_vhisperx(video_file):
print(video_file)
subprocess.run(["sh", "vhisperx", "--vid", video_file])
# Function to read the output file generated by vhisperx
def read_output_file(directory, video_name):
output_file_path = os.path.join(directory, video_name, "output_file.txt")
with open(output_file_path, "r") as file:
return file.read()
# Function to send text to an API and get a concise name as a response
def send_to_api(text, client, model="gpt-4o-mini"):
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": f"""Pick a concise name in english for the following transcription of a video.
The transcription may have various typos in it and yet you are expected to pick a concise name for the video.
BECAREFUL where this name is for a file name and has to be in english. ONLY SEND the FILE NAME, WITHOUT special chars like _ or $ etc : {text}"""},
],
max_tokens=50 # Adjust the max_tokens as needed
)
return response.choices[0].message.content.strip()
# Function to send multiple texts to an API and get precise names as a response
def send_multiple_to_api(texts, client, model="gpt-4o-mini"):
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": f"""Pick precise and distinct concise names in english for the following transcriptions of videos.
The transcriptions may have various typos in it and yet you are expected to pick concise names for the videos.
BECAREFUL where these names are for file names and have to be in english. ONLY SEND the FILE NAMES, WITHOUT special chars like _ or $ etc, separated by a newline:
{texts}"""},
]
response = client.chat.completions.create(
model=model,
messages=messages,
max_tokens=100 # Adjust the max_tokens as needed
)
return response.choices[0].message.content.strip().split('\n')
# Function to rename a video file and its corresponding directory to a new name
def rename_video(video_file, new_name):
directory = os.path.dirname(video_file)
video_name = os.path.splitext(os.path.basename(video_file))[0]
# Rename the video file
new_video_file = os.path.join(directory, new_name + ".mp4")
os.rename(video_file, new_video_file)
# Rename the directory containing the output_file.txt
old_directory = os.path.join(directory, video_name)
new_directory = os.path.join(directory, new_name)
os.rename(old_directory, new_directory)
return new_video_file
# Function to log a task to a log file
def log_task(log_file, task):
with open(log_file, "a") as file:
file.write(task + "\n")
# Function to check if a video file has been processed before
def is_processed(log_file, video_name):
with open(log_file, "r") as file:
for line in file:
if video_name in line:
return True
return False
# Main function to process video files in a directory
def main():
load_dotenv()
api_key = os.environ['API_KEY']
base_url = os.getenv('BASE_URL', 'https://api.together.xyz/v1')
model = os.getenv('MODEL', 'meta-llama/Llama-3.3-70B-Instruct-Turbo')
client = openai.OpenAI(api_key=api_key, base_url=base_url)
colorama.init(autoreset=True)
if len(sys.argv) != 3 or sys.argv[1] != "-d":
print(Fore.RED + "Usage: python script.py -d <directory>")
sys.exit(1)
directory = sys.argv[2]
video_files = get_video_files(directory)
log_file = "1video-titler.txt"
if not video_files:
print(Fore.YELLOW + "No video files found in the directory.")
log_task(log_file, "No video files found in the directory.")
sys.exit(0)
for video_file in video_files:
video_name = os.path.splitext(os.path.basename(video_file))[0]
print(Fore.CYAN + f"Processing video: {video_name}")
if is_processed(log_file, video_name):
print(Fore.YELLOW + f"Video {video_name} has already been processed.")
continue
output_file_path = os.path.join(directory, video_name, "output_file.txt")
if not os.path.exists(output_file_path):
run_vhisperx(video_file)
print(Fore.GREEN + f"vhisperx completed for {video_name}")
else:
print(Fore.GREEN + f"vhisperx output_file.txt found for {video_name}")
output_text = read_output_file(directory, video_name)
print(Fore.GREEN + f"Output file read for {video_name}")
concise_name = send_to_api(output_text, client, model)
print(Fore.GREEN + f"Concise name received from API for {video_name}: {concise_name}")
# Check for conflicts
if os.path.exists(os.path.join(directory, concise_name + ".mp4")):
print(Fore.YELLOW + f"Conflict detected: {concise_name} already exists. Requesting more precise names.")
# Collect all conflicting videos
conflicting_videos = [(video_file, output_text, concise_name)]
for other_video_file in video_files:
other_video_name = os.path.splitext(os.path.basename(other_video_file))[0]
if other_video_name != video_name:
other_output_file_path = os.path.join(directory, other_video_name, "output_file.txt")
if os.path.exists(other_output_file_path):
other_output_text = read_output_file(directory, other_video_name)
other_concise_name = send_to_api(other_output_text, client, model)
if other_concise_name == concise_name:
conflicting_videos.append((other_video_file, other_output_text, other_concise_name))
# Send all conflicting transcriptions to the API for more precise names
texts = "\n".join([video[1] for video in conflicting_videos])
precise_names = send_multiple_to_api(texts, client, model)
print(Fore.GREEN + f"Precise names received from API: {precise_names}")
# Rename all conflicting videos
for (video_file, _, _), new_name in zip(conflicting_videos, precise_names):
new_video_file = rename_video(video_file, new_name)
print(Fore.GREEN + f"Video and directory renamed to: {new_video_file}")
log_task(log_file, f"Processed {os.path.splitext(os.path.basename(video_file))[0]} and renamed to {new_name}")
else:
new_video_file = rename_video(video_file, concise_name)
print(Fore.GREEN + f"Video and directory renamed to: {new_video_file}")
log_task(log_file, f"Processed {video_name} and renamed to {concise_name}")
print(Fore.MAGENTA + "All tasks completed. Check 1video-titler.txt for the log.")
if __name__ == "__main__":
main()