captions
Browse files- create_captions.py +111 -0
- extract_metadata.py +40 -10
- grok_analyze.py +42 -21
- transcripts_editing.py +71 -0
- upload_to_s3.py +33 -5
create_captions.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ffmpeg
|
| 2 |
+
import sys
|
| 3 |
+
import re
|
| 4 |
+
import subprocess
|
| 5 |
+
import os
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def time_to_float(time_str):
|
| 10 |
+
# Split the time string into minutes, seconds, and milliseconds
|
| 11 |
+
minutes, seconds = time_str.split(':')
|
| 12 |
+
seconds, milliseconds = seconds.split('.')
|
| 13 |
+
|
| 14 |
+
# Convert to float (total seconds)
|
| 15 |
+
return float(minutes) * 60 + float(seconds) + float(milliseconds) / 1000
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def create_caps(steps):
|
| 19 |
+
captions=[]
|
| 20 |
+
video_start=0
|
| 21 |
+
for step in steps:
|
| 22 |
+
print(step)
|
| 23 |
+
start=time_to_float(step['start'])
|
| 24 |
+
end= time_to_float(step['end'])
|
| 25 |
+
description_sentences=step['description'].split(".")
|
| 26 |
+
|
| 27 |
+
print(description_sentences)
|
| 28 |
+
|
| 29 |
+
interval=end/len(description_sentences)
|
| 30 |
+
start_interval=video_start
|
| 31 |
+
|
| 32 |
+
for description_sentence in description_sentences:
|
| 33 |
+
caption=(start_interval,start_interval+interval,description_sentence)
|
| 34 |
+
start_interval+=interval
|
| 35 |
+
captions.append(caption)
|
| 36 |
+
video_start+=end
|
| 37 |
+
|
| 38 |
+
return captions
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def create_srt(subtitles, output_file):
|
| 44 |
+
with open(output_file, 'w', encoding='utf-8') as f:
|
| 45 |
+
for i, (start, end, text) in enumerate(subtitles, 1):
|
| 46 |
+
start_time = f"{int(start//3600):02d}:{int((start%3600)//60):02d}:{int(start%60):02d},{int((start%1)*1000):03d}"
|
| 47 |
+
end_time = f"{int(end//3600):02d}:{int((end%3600)//60):02d}:{int(end%60):02d},{int((end%1)*1000):03d}"
|
| 48 |
+
f.write(f"{i}\n{start_time} --> {end_time}\n{text}\n\n")
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def add_captions_to_video(input_video,soft_subtitle, subtitles,output_video="output_video_subtitles.mp4",subtitle_language="en"):
|
| 53 |
+
subtitle_file="subtitles.srt"
|
| 54 |
+
create_srt(subtitles,subtitle_file)
|
| 55 |
+
|
| 56 |
+
video_input_stream = ffmpeg.input(input_video)
|
| 57 |
+
subtitle_input_stream = ffmpeg.input(subtitle_file)
|
| 58 |
+
output_video = output_video
|
| 59 |
+
subtitle_track_title = subtitle_file.replace(".srt", "")
|
| 60 |
+
|
| 61 |
+
if soft_subtitle:
|
| 62 |
+
stream = ffmpeg.output(
|
| 63 |
+
video_input_stream, subtitle_input_stream, output_video, **{"c": "copy", "c:s": "mov_text"},
|
| 64 |
+
**{"metadata:s:s:0": f"language={subtitle_language}",
|
| 65 |
+
"metadata:s:s:0": f"title={subtitle_track_title}"}
|
| 66 |
+
)
|
| 67 |
+
ffmpeg.run(stream, overwrite_output=True)
|
| 68 |
+
else:
|
| 69 |
+
subtitle_style = (
|
| 70 |
+
"force_style='FontName=Arial,FontSize=15,PrimaryColour=&H00FFFFFF,"
|
| 71 |
+
"Alignment=2,MarginV=25'"
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
stream = ffmpeg.output(
|
| 75 |
+
video_input_stream,
|
| 76 |
+
output_video,
|
| 77 |
+
**{
|
| 78 |
+
"c:v": "h264_videotoolbox",
|
| 79 |
+
# "q:v": 50, # Specify video codec (H.264)
|
| 80 |
+
"c:a": "copy", # Copy audio stream to avoid re-encoding
|
| 81 |
+
"vf": f"subtitles={subtitle_file}:{subtitle_style}", # Burn subtitles
|
| 82 |
+
"threads": 0
|
| 83 |
+
}
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
print("here")
|
| 87 |
+
ffmpeg.run(stream, overwrite_output=True)
|
| 88 |
+
|
| 89 |
+
return output_video
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
if __name__ == "__main__":
|
| 98 |
+
# Example subtitles
|
| 99 |
+
subtitles = [
|
| 100 |
+
(0, 4, "Hello, this is the first subtitle."),
|
| 101 |
+
(5, 10, "This is the second subtitle.")
|
| 102 |
+
]
|
| 103 |
+
# create_srt(subtitles, "subtitles.srt")
|
| 104 |
+
|
| 105 |
+
# Input video and subtitle files
|
| 106 |
+
input_video = "/Users/georgia.bucea/products/ShortsAI/21_aug/IMG_8280.MOV"
|
| 107 |
+
subtitle_file = "subtitles.srt"
|
| 108 |
+
output_video = "output_video_subtitles.mp4"
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
add_captions_to_video(input_video,False,subtitles,output_video,"en")
|
extract_metadata.py
CHANGED
|
@@ -11,6 +11,7 @@ from grok_analyze import analyze_image_with_grok_f
|
|
| 11 |
import json
|
| 12 |
import random
|
| 13 |
import string
|
|
|
|
| 14 |
def extract_scenes_scenedetect(video_path, threshold=30.0, min_scene_duration=5.0):
|
| 15 |
|
| 16 |
vid_obj={"type":"video", "path":video_path}
|
|
@@ -97,6 +98,7 @@ def extract_scenes_scenedetect(video_path, threshold=30.0, min_scene_duration=5.
|
|
| 97 |
return vid_obj
|
| 98 |
|
| 99 |
|
|
|
|
| 100 |
def get_metadata(all_files):
|
| 101 |
|
| 102 |
all_files_info=[]
|
|
@@ -109,26 +111,54 @@ def get_metadata(all_files):
|
|
| 109 |
random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
|
| 110 |
file_name = f"all_files_info_{random_string}.json"
|
| 111 |
|
|
|
|
|
|
|
| 112 |
with open(file_name, "w") as file:
|
| 113 |
json.dump(all_files_info, file, indent=4)
|
|
|
|
|
|
|
| 114 |
|
| 115 |
return all_files_info,file_name
|
| 116 |
|
| 117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
|
| 119 |
|
| 120 |
if __name__ == "__main__":
|
| 121 |
-
all_files_info=[]
|
| 122 |
-
dir_path="/Users/georgia.bucea/products/ShortsAI/21_aug"
|
| 123 |
-
all_files=read_files(dir_path)
|
| 124 |
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
|
|
|
|
|
|
| 11 |
import json
|
| 12 |
import random
|
| 13 |
import string
|
| 14 |
+
import random
|
| 15 |
def extract_scenes_scenedetect(video_path, threshold=30.0, min_scene_duration=5.0):
|
| 16 |
|
| 17 |
vid_obj={"type":"video", "path":video_path}
|
|
|
|
| 98 |
return vid_obj
|
| 99 |
|
| 100 |
|
| 101 |
+
|
| 102 |
def get_metadata(all_files):
|
| 103 |
|
| 104 |
all_files_info=[]
|
|
|
|
| 111 |
random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
|
| 112 |
file_name = f"all_files_info_{random_string}.json"
|
| 113 |
|
| 114 |
+
|
| 115 |
+
|
| 116 |
with open(file_name, "w") as file:
|
| 117 |
json.dump(all_files_info, file, indent=4)
|
| 118 |
+
|
| 119 |
+
# upload_to_s3(file_name,"bucket","s3key")
|
| 120 |
|
| 121 |
return all_files_info,file_name
|
| 122 |
|
| 123 |
|
| 124 |
+
def get_scenes_metadata(metadata, no_scenes=10):
|
| 125 |
+
|
| 126 |
+
selected = []
|
| 127 |
+
while len(selected) < no_scenes and metadata: # Pick 3, stop if list empties
|
| 128 |
+
item = random.choice(metadata)
|
| 129 |
+
selected.append(item)
|
| 130 |
+
metadata.remove(item)
|
| 131 |
+
|
| 132 |
+
# print(selected)
|
| 133 |
+
# print(len(selected))
|
| 134 |
+
|
| 135 |
+
return(selected)
|
| 136 |
+
|
| 137 |
+
|
| 138 |
|
| 139 |
|
| 140 |
if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
+
with open('/Users/georgia.bucea/products/ShortsAI/all_files_metadata.json', 'r') as file:
|
| 143 |
+
data = json.load(file)
|
| 144 |
+
print(len(data))
|
| 145 |
+
get_scenes_metadata(data)
|
| 146 |
+
# all_files_info=[]
|
| 147 |
+
# # dir_path="/Users/georgia.bucea/products/ShortsAI/21_aug"
|
| 148 |
+
# # all_files=read_files(dir_path)
|
| 149 |
+
# dir_path="/Users/georgia.bucea/products/ShortsAI/16_aug"
|
| 150 |
+
# # all_files2=read_files(dir_path)
|
| 151 |
+
# all_files=read_files(dir_path)
|
| 152 |
|
| 153 |
+
# # all_files=all_files+all_files2
|
| 154 |
+
# for file in all_files:
|
| 155 |
+
# file_path=dir_path+"/"+file
|
| 156 |
+
# if file_path.split(".")[-1] in ["MOV","mp4"]:
|
| 157 |
+
# vid_info=extract_scenes_scenedetect(file_path)
|
| 158 |
+
# all_files_info.append(vid_info)
|
| 159 |
+
|
| 160 |
+
# with open("all_files_info_21_aug_16_aug.json", "w") as file:
|
| 161 |
+
# json.dump(all_files_info, file, indent=4)
|
| 162 |
|
| 163 |
|
| 164 |
+
|
grok_analyze.py
CHANGED
|
@@ -1,10 +1,14 @@
|
|
| 1 |
import os
|
| 2 |
import base64
|
|
|
|
|
|
|
|
|
|
| 3 |
from xai_sdk import Client
|
| 4 |
from xai_sdk.chat import user, image
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
import cv2
|
| 7 |
import json
|
|
|
|
| 8 |
load_dotenv()
|
| 9 |
|
| 10 |
def encode_image_to_base64_f(frame):
|
|
@@ -67,13 +71,12 @@ def analyze_image_with_grok_f( frame):
|
|
| 67 |
except Exception as e:
|
| 68 |
return f"Error during API call: {str(e)}"
|
| 69 |
|
| 70 |
-
def get_story_with_grok(
|
| 71 |
# Initialize xAI client
|
| 72 |
api_key = os.getenv("X_AI")
|
| 73 |
client = Client(
|
| 74 |
api_key=api_key,
|
| 75 |
)
|
| 76 |
-
|
| 77 |
# Create chat session
|
| 78 |
chat = client.chat.create(model="grok-4-0709") # Use vision-capable model
|
| 79 |
print(current_context)
|
|
@@ -81,13 +84,17 @@ def get_story_with_grok(context,current_context):
|
|
| 81 |
# Append user message with base64-encoded image
|
| 82 |
chat.append(
|
| 83 |
user(
|
| 84 |
-
"Based on the following context,
|
| 85 |
-
|
| 86 |
-
|
|
|
|
| 87 |
else:
|
|
|
|
| 88 |
chat.append(
|
| 89 |
user(
|
| 90 |
-
"Based on the following context, generate
|
|
|
|
|
|
|
| 91 |
)
|
| 92 |
)
|
| 93 |
|
|
@@ -95,32 +102,46 @@ def get_story_with_grok(context,current_context):
|
|
| 95 |
response = chat.sample()
|
| 96 |
data= response.content
|
| 97 |
video_data = json.loads(data)
|
| 98 |
-
|
|
|
|
| 99 |
except Exception as e:
|
| 100 |
return f"Error during API call: {str(e)}"
|
| 101 |
|
| 102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
def main():
|
| 104 |
-
# Your xAI API key
|
| 105 |
-
# Path to your image
|
| 106 |
-
# image_path = "/Users/georgia.bucea/products/ShortsAI/frames_scenesdetect/scene_0000.jpg"
|
| 107 |
-
|
| 108 |
-
# # Verify image path exists
|
| 109 |
-
# if not os.path.exists(image_path):
|
| 110 |
-
# print(f"Error: Image file not found at {image_path}")
|
| 111 |
-
# return
|
| 112 |
-
|
| 113 |
-
# print("Analyzing image...")
|
| 114 |
-
# analysis = analyze_image_with_grok_f( image_path)
|
| 115 |
-
# print("Grok's Analysis:")
|
| 116 |
-
# print(analysis)
|
| 117 |
|
| 118 |
context_path="/Users/georgia.bucea/products/ShortsAI/all_files_metadata.json"
|
| 119 |
with open(context_path, 'r') as file:
|
| 120 |
|
| 121 |
data = json.load(file)
|
| 122 |
print("here we are")
|
| 123 |
-
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
|
| 126 |
|
|
|
|
| 1 |
import os
|
| 2 |
import base64
|
| 3 |
+
|
| 4 |
+
from torch.cuda import temperature
|
| 5 |
+
|
| 6 |
from xai_sdk import Client
|
| 7 |
from xai_sdk.chat import user, image
|
| 8 |
from dotenv import load_dotenv
|
| 9 |
import cv2
|
| 10 |
import json
|
| 11 |
+
from create_captions import create_caps
|
| 12 |
load_dotenv()
|
| 13 |
|
| 14 |
def encode_image_to_base64_f(frame):
|
|
|
|
| 71 |
except Exception as e:
|
| 72 |
return f"Error during API call: {str(e)}"
|
| 73 |
|
| 74 |
+
def get_story_with_grok(metadata,current_context,dialog):
|
| 75 |
# Initialize xAI client
|
| 76 |
api_key = os.getenv("X_AI")
|
| 77 |
client = Client(
|
| 78 |
api_key=api_key,
|
| 79 |
)
|
|
|
|
| 80 |
# Create chat session
|
| 81 |
chat = client.chat.create(model="grok-4-0709") # Use vision-capable model
|
| 82 |
print(current_context)
|
|
|
|
| 84 |
# Append user message with base64-encoded image
|
| 85 |
chat.append(
|
| 86 |
user(
|
| 87 |
+
# "Based on the following context, the phrase: "+current_context+ " and the given dialog, generate an engaging random story relevant to the dialog with no more than 4 scenes.The description should be short engaging, relevant to the dialog, with less adjectives, with no more than three short sentences, in present tense and first person. The story should be given as JSON, with the scenes in the following format:scenes:[path:file_path,start:,end:,description:].The path is extracted from the metadata file. Do not include a title, a main description, or anything else besides the scenes in the story as JSON format. The metadata: " + str(metadata) + " And the following dialog: "+ dialog,
|
| 88 |
+
"Based on the following metadata,the phrase: "+current_context+ ", and the given dialog, generate an engaging story with no more than 4 scenes. The story should be given as JSON, with the scenes in the following format:scenes:[path:file_path,start:,end:,description:].The path is extracted from the metadata file. Do not include a title, a main description, or anything else besides the scenes in the story as JSON format. The metadata: " + str(metadata) + " And the following dialog: "+ dialog,
|
| 89 |
+
|
| 90 |
+
))
|
| 91 |
else:
|
| 92 |
+
print("here")
|
| 93 |
chat.append(
|
| 94 |
user(
|
| 95 |
+
# "Based on the following context and the given dialog, generate an engaging random story with no more than 4 scenes extracted randomly from the given metadata. The description should be short engaging, relevant to the given dialog,with less adjectives. with no more than three short sentences that take into account the transcripted dialog, in present tense and first person. The story should be given as JSON, with the scenes in the following format:scenes:[path:file_path,start:,end:,description:].The path is extracted from the metadata file. Do not include a title, a main description, or anything else besides the scenes in the story as JSON format. The metadata: " + str(metadata) + " And the following dialog: "+ dialog,
|
| 96 |
+
"You are a vlogger, making videos about your life and your adventures. Based on the following metadata and the given dialog, generate an engaging story with no more than 4 scenes related to the metadata. Use less adjectives with short sentences. The story should be given as JSON, with the scenes in the following format:scenes:[path:file_path,start:,end:,description:].The path is extracted from the metadata file. Do not include a title, a main description, or anything else besides the scenes in the story as JSON format. The metadata: " + str(metadata) + " And the following dialog: "+ dialog,
|
| 97 |
+
# "Based on the following metadata and the given dialog, generate an engaging story with all scenes in the metadata. The story should be given as JSON, with the scenes in the following format:scenes:[path:file_path,start:,end:,description:].The path is extracted from the metadata file. Do not include a title, a main description, or anything else besides the scenes in the story as JSON format. The metadata: " + str(metadata) + " And the following dialog: "+ dialog,
|
| 98 |
)
|
| 99 |
)
|
| 100 |
|
|
|
|
| 102 |
response = chat.sample()
|
| 103 |
data= response.content
|
| 104 |
video_data = json.loads(data)
|
| 105 |
+
print(video_data)
|
| 106 |
+
return video_data['scenes']
|
| 107 |
except Exception as e:
|
| 108 |
return f"Error during API call: {str(e)}"
|
| 109 |
|
| 110 |
|
| 111 |
+
|
| 112 |
+
def create_caps_with_grok(steps):
|
| 113 |
+
api_key = os.getenv("X_AI")
|
| 114 |
+
client = Client(
|
| 115 |
+
api_key=api_key,
|
| 116 |
+
)
|
| 117 |
+
# chat = client.chat.create(model="grok-4-0709")
|
| 118 |
+
for step in steps:
|
| 119 |
+
chat = client.chat.create(model="grok-4-0709")
|
| 120 |
+
chat.append(
|
| 121 |
+
user(
|
| 122 |
+
"You are a vlogger, making videos about your life. Based on the following description generate a short caption, with no more than three short sentences, less adjectives, in present tense, first person that is fit for a story. Do not include a title or anython else besides the final caption. the description: "+step["description"],
|
| 123 |
+
))
|
| 124 |
+
try:
|
| 125 |
+
response = chat.sample()
|
| 126 |
+
data= response.content
|
| 127 |
+
step["description"]=data
|
| 128 |
+
except Exception as e:
|
| 129 |
+
return f"Error during API call: {str(e)}"
|
| 130 |
+
return steps
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
|
| 134 |
def main():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
|
| 136 |
context_path="/Users/georgia.bucea/products/ShortsAI/all_files_metadata.json"
|
| 137 |
with open(context_path, 'r') as file:
|
| 138 |
|
| 139 |
data = json.load(file)
|
| 140 |
print("here we are")
|
| 141 |
+
steps=get_story_with_grok(data,"")
|
| 142 |
+
print(steps)
|
| 143 |
+
steps=create_caps_with_grok(steps)
|
| 144 |
+
print(steps)
|
| 145 |
|
| 146 |
|
| 147 |
|
transcripts_editing.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv
|
| 2 |
+
import requests
|
| 3 |
+
import os
|
| 4 |
+
load_dotenv()
|
| 5 |
+
|
| 6 |
+
# Access the variables
|
| 7 |
+
api_key = os.getenv("DEVICE_ID")
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def parse_response(data):
|
| 11 |
+
|
| 12 |
+
dialog = []
|
| 13 |
+
for i in range(len(data['memories'])):
|
| 14 |
+
for segment in data['memories'][i]['transcript_segments']:
|
| 15 |
+
speaker = segment['speaker']
|
| 16 |
+
start_time = segment['start']
|
| 17 |
+
end_time = segment['end']
|
| 18 |
+
# Fallback for unexpected speaker IDs
|
| 19 |
+
dialog.append(f"**{speaker}**: {segment['text']}")
|
| 20 |
+
|
| 21 |
+
# Join dialog lines into a markdown string
|
| 22 |
+
dialog_text = "\n\n".join(dialog)
|
| 23 |
+
|
| 24 |
+
return dialog_text
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def fetch_memories(url, headers, cursor=None):
|
| 29 |
+
# Update URL with cursor if provided
|
| 30 |
+
if cursor:
|
| 31 |
+
url = f"{url}&cursor={cursor}"
|
| 32 |
+
|
| 33 |
+
response = requests.get(url, headers=headers)
|
| 34 |
+
|
| 35 |
+
if response.status_code == 200:
|
| 36 |
+
return response.json()
|
| 37 |
+
else:
|
| 38 |
+
print(f"Error: {response.status_code} - {response.text}")
|
| 39 |
+
return None
|
| 40 |
+
|
| 41 |
+
# Initial API setup
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def get_dialog(date="2025-08-21"):
|
| 46 |
+
url = "https://apis.getbuddi.ai/v1/dev/get_memories?date="+date
|
| 47 |
+
headers = {
|
| 48 |
+
"api-key": api_key
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
dialog=""
|
| 52 |
+
# Fetch first batch
|
| 53 |
+
data = fetch_memories(url, headers)
|
| 54 |
+
if data:
|
| 55 |
+
# print("First batch:", data)
|
| 56 |
+
|
| 57 |
+
# Check for next_cursor and fetch subsequent batches
|
| 58 |
+
while 'next_cursor' in data and data['next_cursor']:
|
| 59 |
+
cursor = data['next_cursor']
|
| 60 |
+
print(cursor)
|
| 61 |
+
data = fetch_memories(url, headers, cursor)
|
| 62 |
+
if data:
|
| 63 |
+
dialog=dialog+parse_response(data)
|
| 64 |
+
# print("Next batch:", data)
|
| 65 |
+
else:
|
| 66 |
+
break
|
| 67 |
+
return(dialog)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
if __name__ == "__main__":
|
| 71 |
+
print(get_dialog())
|
upload_to_s3.py
CHANGED
|
@@ -9,6 +9,29 @@ BUCKET = "shortsai-us" # Replace with your bucket name
|
|
| 9 |
S3_KEY = "test/IMG_8280.MOV" # S3 path for the file
|
| 10 |
LOCAL_FILE_PATH = "/Users/georgia.bucea/products/ShortsAI/21_aug/mcp_video-3028_singular_display.MOV" # Replace with your local file path
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
load_dotenv()
|
| 13 |
|
| 14 |
# Access the variables
|
|
@@ -61,7 +84,7 @@ def upload_multiple_files(file_list, bucket):
|
|
| 61 |
print(f"Unexpected error: {e}")
|
| 62 |
return False
|
| 63 |
|
| 64 |
-
with ThreadPoolExecutor(max_workers=
|
| 65 |
executor.map(lambda f: upload_to_s3(f[0], bucket, f[1]), file_list)
|
| 66 |
return uploaded_files
|
| 67 |
|
|
@@ -70,9 +93,14 @@ if __name__ == "__main__":
|
|
| 70 |
# upload_to_s3(LOCAL_FILE_PATH,BUCKET,S3_KEY)
|
| 71 |
bucket = os.getenv("BUCKET")
|
| 72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
-
file_list = [
|
| 75 |
-
("/Users/georgia.bucea/products/ShortsAI/21_aug/mcp_video-3028_singular_display.MOV", "test/21_aug/mcp_video-3028_singular_display.MOV"),
|
| 76 |
-
]
|
| 77 |
|
| 78 |
-
uploaded = upload_multiple_files(
|
|
|
|
| 9 |
S3_KEY = "test/IMG_8280.MOV" # S3 path for the file
|
| 10 |
LOCAL_FILE_PATH = "/Users/georgia.bucea/products/ShortsAI/21_aug/mcp_video-3028_singular_display.MOV" # Replace with your local file path
|
| 11 |
|
| 12 |
+
import os
|
| 13 |
+
|
| 14 |
+
def list_files_in_folder(folder_path: str) -> list:
|
| 15 |
+
"""
|
| 16 |
+
Reads all files in the specified folder (non-recursive, excludes subdirectories).
|
| 17 |
+
|
| 18 |
+
:param folder_path: Path to the folder.
|
| 19 |
+
:return: List of file names.
|
| 20 |
+
"""
|
| 21 |
+
try:
|
| 22 |
+
# Check if folder exists
|
| 23 |
+
if not os.path.isdir(folder_path):
|
| 24 |
+
raise ValueError(f"Directory does not exist: {folder_path}")
|
| 25 |
+
|
| 26 |
+
# List all entries in the folder, filter for files only
|
| 27 |
+
files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
|
| 28 |
+
return files
|
| 29 |
+
except Exception as e:
|
| 30 |
+
print(f"Error reading folder: {e}")
|
| 31 |
+
return []
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
|
| 35 |
load_dotenv()
|
| 36 |
|
| 37 |
# Access the variables
|
|
|
|
| 84 |
print(f"Unexpected error: {e}")
|
| 85 |
return False
|
| 86 |
|
| 87 |
+
with ThreadPoolExecutor(max_workers=30) as executor:
|
| 88 |
executor.map(lambda f: upload_to_s3(f[0], bucket, f[1]), file_list)
|
| 89 |
return uploaded_files
|
| 90 |
|
|
|
|
| 93 |
# upload_to_s3(LOCAL_FILE_PATH,BUCKET,S3_KEY)
|
| 94 |
bucket = os.getenv("BUCKET")
|
| 95 |
|
| 96 |
+
folder="/Users/georgia.bucea/products/ShortsAI/16_aug"
|
| 97 |
+
|
| 98 |
+
files=list_files_in_folder("/Users/georgia.bucea/products/ShortsAI/16_aug")
|
| 99 |
+
files=[(folder+ "/"+os.path.basename(path), "testall16/"+os.path.basename(path)) for path in files]
|
| 100 |
+
print(files)
|
| 101 |
|
| 102 |
+
# file_list = [
|
| 103 |
+
# ("/Users/georgia.bucea/products/ShortsAI/21_aug/mcp_video-3028_singular_display.MOV", "test/21_aug/mcp_video-3028_singular_display.MOV"),
|
| 104 |
+
# ]
|
| 105 |
|
| 106 |
+
uploaded = upload_multiple_files(files, bucket)
|