Merge pull request #368 from harry0703/dev
enhanced exception handling for llm and optimized video concatenation
This commit is contained in:
@@ -9,6 +9,8 @@ from openai.types.chat import ChatCompletion
|
|||||||
|
|
||||||
from app.config import config
|
from app.config import config
|
||||||
|
|
||||||
|
_max_retries = 5
|
||||||
|
|
||||||
|
|
||||||
def _generate_response(prompt: str) -> str:
|
def _generate_response(prompt: str) -> str:
|
||||||
content = ""
|
content = ""
|
||||||
@@ -219,11 +221,8 @@ Generate a script for a video, depending on the subject of the video.
|
|||||||
|
|
||||||
final_script = ""
|
final_script = ""
|
||||||
logger.info(f"subject: {video_subject}")
|
logger.info(f"subject: {video_subject}")
|
||||||
# logger.debug(f"prompt: \n{prompt}")
|
|
||||||
response = _generate_response(prompt=prompt)
|
|
||||||
|
|
||||||
# Return the generated script
|
def format_response(response):
|
||||||
if response:
|
|
||||||
# Clean the script
|
# Clean the script
|
||||||
# Remove asterisks, hashes
|
# Remove asterisks, hashes
|
||||||
response = response.replace("*", "")
|
response = response.replace("*", "")
|
||||||
@@ -240,19 +239,30 @@ Generate a script for a video, depending on the subject of the video.
|
|||||||
selected_paragraphs = paragraphs[:paragraph_number]
|
selected_paragraphs = paragraphs[:paragraph_number]
|
||||||
|
|
||||||
# Join the selected paragraphs into a single string
|
# Join the selected paragraphs into a single string
|
||||||
final_script = "\n\n".join(selected_paragraphs)
|
return "\n\n".join(selected_paragraphs)
|
||||||
|
|
||||||
# Print to console the number of paragraphs used
|
for i in range(_max_retries):
|
||||||
# logger.info(f"number of paragraphs used: {len(selected_paragraphs)}")
|
try:
|
||||||
else:
|
response = _generate_response(prompt=prompt)
|
||||||
logging.error("gpt returned an empty response")
|
if response:
|
||||||
|
final_script = format_response(response)
|
||||||
|
else:
|
||||||
|
logging.error("gpt returned an empty response")
|
||||||
|
|
||||||
# g4f may return an error message
|
# g4f may return an error message
|
||||||
if final_script and "当日额度已消耗完" in final_script:
|
if final_script and "当日额度已消耗完" in final_script:
|
||||||
raise ValueError(final_script)
|
raise ValueError(final_script)
|
||||||
|
|
||||||
|
if final_script:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"failed to generate script: {e}")
|
||||||
|
|
||||||
|
if i < _max_retries:
|
||||||
|
logger.warning(f"failed to generate video script, trying again... {i + 1}")
|
||||||
|
|
||||||
logger.success(f"completed: \n{final_script}")
|
logger.success(f"completed: \n{final_script}")
|
||||||
return final_script
|
return final_script.strip()
|
||||||
|
|
||||||
|
|
||||||
def generate_terms(video_subject: str, video_script: str, amount: int = 5) -> List[str]:
|
def generate_terms(video_subject: str, video_script: str, amount: int = 5) -> List[str]:
|
||||||
@@ -283,25 +293,28 @@ Please note that you must use English for generating video search terms; Chinese
|
|||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
logger.info(f"subject: {video_subject}")
|
logger.info(f"subject: {video_subject}")
|
||||||
# logger.debug(f"prompt: \n{prompt}")
|
|
||||||
response = _generate_response(prompt)
|
|
||||||
search_terms = []
|
search_terms = []
|
||||||
|
for i in range(_max_retries):
|
||||||
|
try:
|
||||||
|
response = _generate_response(prompt)
|
||||||
|
search_terms = json.loads(response)
|
||||||
|
if not isinstance(search_terms, list) or not all(isinstance(term, str) for term in search_terms):
|
||||||
|
logger.error("response is not a list of strings.")
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
except Exception as e:
|
||||||
search_terms = json.loads(response)
|
match = re.search(r'\[.*]', response)
|
||||||
if not isinstance(search_terms, list) or not all(isinstance(term, str) for term in search_terms):
|
if match:
|
||||||
raise ValueError("response is not a list of strings.")
|
try:
|
||||||
|
search_terms = json.loads(match.group())
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
except (json.JSONDecodeError, ValueError):
|
if search_terms and len(search_terms) > 0:
|
||||||
# logger.warning(f"gpt returned an unformatted response. attempting to clean...")
|
break
|
||||||
# Attempt to extract list-like string and convert to list
|
if i < _max_retries:
|
||||||
match = re.search(r'\["(?:[^"\\]|\\.)*"(?:,\s*"[^"\\]*")*\]', response)
|
logger.warning(f"failed to generate video terms, trying again... {i + 1}")
|
||||||
if match:
|
|
||||||
try:
|
|
||||||
search_terms = json.loads(match.group())
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
logger.error(f"could not parse response: {response}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
logger.success(f"completed: \n{search_terms}")
|
logger.success(f"completed: \n{search_terms}")
|
||||||
return search_terms
|
return search_terms
|
||||||
@@ -310,8 +323,8 @@ Please note that you must use English for generating video search terms; Chinese
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
video_subject = "生命的意义是什么"
|
video_subject = "生命的意义是什么"
|
||||||
script = generate_script(video_subject=video_subject, language="zh-CN", paragraph_number=1)
|
script = generate_script(video_subject=video_subject, language="zh-CN", paragraph_number=1)
|
||||||
# print("######################")
|
print("######################")
|
||||||
# print(script)
|
print(script)
|
||||||
# search_terms = generate_terms(video_subject=video_subject, video_script=script, amount=5)
|
search_terms = generate_terms(video_subject=video_subject, video_script=script, amount=5)
|
||||||
# print("######################")
|
print("######################")
|
||||||
# print(search_terms)
|
print(search_terms)
|
||||||
|
|||||||
@@ -60,15 +60,17 @@ def combine_videos(combined_video_path: str,
|
|||||||
end_time = min(start_time + max_clip_duration, clip_duration)
|
end_time = min(start_time + max_clip_duration, clip_duration)
|
||||||
split_clip = clip.subclip(start_time, end_time)
|
split_clip = clip.subclip(start_time, end_time)
|
||||||
raw_clips.append(split_clip)
|
raw_clips.append(split_clip)
|
||||||
logger.info(f"splitting from {start_time:.2f} to {end_time:.2f}, clip duration {clip_duration:.2f}, split_clip duration {split_clip.duration:.2f}")
|
# logger.info(f"splitting from {start_time:.2f} to {end_time:.2f}, clip duration {clip_duration:.2f}, split_clip duration {split_clip.duration:.2f}")
|
||||||
start_time = end_time
|
start_time = end_time
|
||||||
|
if video_concat_mode.value == VideoConcatMode.sequential.value:
|
||||||
|
break
|
||||||
|
|
||||||
|
# random video_paths order
|
||||||
|
if video_concat_mode.value == VideoConcatMode.random.value:
|
||||||
|
random.shuffle(raw_clips)
|
||||||
|
|
||||||
# Add downloaded clips over and over until the duration of the audio (max_duration) has been reached
|
# Add downloaded clips over and over until the duration of the audio (max_duration) has been reached
|
||||||
while video_duration < audio_duration:
|
while video_duration < audio_duration:
|
||||||
# random video_paths order
|
|
||||||
if video_concat_mode.value == VideoConcatMode.random.value:
|
|
||||||
random.shuffle(raw_clips)
|
|
||||||
|
|
||||||
|
|
||||||
for clip in raw_clips:
|
for clip in raw_clips:
|
||||||
# Check if clip is longer than the remaining audio
|
# Check if clip is longer than the remaining audio
|
||||||
if (audio_duration - video_duration) < clip.duration:
|
if (audio_duration - video_duration) < clip.duration:
|
||||||
|
|||||||
Reference in New Issue
Block a user