Delete utils.py
Browse files
utils.py
DELETED
@@ -1,124 +0,0 @@
|
|
1 |
-
import glob
|
2 |
-
import os
|
3 |
-
import random
|
4 |
-
import requests
|
5 |
-
from loguru import logger
|
6 |
-
from moviepy.editor import VideoFileClip, concatenate_videoclips, AudioFileClip, CompositeAudioClip
|
7 |
-
|
8 |
-
def check_file_exists(file_path):
|
9 |
-
if not os.path.exists(file_path):
|
10 |
-
raise FileNotFoundError(f"Tệp {file_path} không tồn tại.")
|
11 |
-
|
12 |
-
# Đường dẫn đầy đủ tới các file
|
13 |
-
bgm_file = "data/bg_music.mp3"
|
14 |
-
output_path = "output/final_video.mp4"
|
15 |
-
|
16 |
-
check_file_exists(bgm_file)
|
17 |
-
|
18 |
-
def get_pexels_video(query):
|
19 |
-
api_key = os.getenv('Pexels_API_KEY')
|
20 |
-
if not api_key:
|
21 |
-
raise ValueError("API key không được tìm thấy trong biến môi trường.")
|
22 |
-
|
23 |
-
url = f"https://api.pexels.com/videos/search?query={query}&per_page=30"
|
24 |
-
headers = {"Authorization": api_key}
|
25 |
-
response = requests.get(url, headers=headers)
|
26 |
-
if response.status_code == 200:
|
27 |
-
data = response.json()
|
28 |
-
if data['videos']:
|
29 |
-
return random.choice(data['videos'])['video_files'][0]['link']
|
30 |
-
logger.error("Không tìm thấy video nào.")
|
31 |
-
return None
|
32 |
-
|
33 |
-
def download_video(url, save_path="downloaded_video.mp4"):
|
34 |
-
try:
|
35 |
-
response = requests.get(url, stream=True)
|
36 |
-
response.raise_for_status()
|
37 |
-
with open(save_path, 'wb') as f:
|
38 |
-
for chunk in response.iter_content(chunk_size=1024):
|
39 |
-
f.write(chunk)
|
40 |
-
return save_path
|
41 |
-
except requests.exceptions.RequestException as e:
|
42 |
-
logger.error(f"Failed to download video from {url}: {e}")
|
43 |
-
return None
|
44 |
-
|
45 |
-
def get_bgm_file(bgm_type: str = "random", bgm_file: str = ""):
|
46 |
-
if not bgm_type:
|
47 |
-
return ""
|
48 |
-
if bgm_type == "random":
|
49 |
-
suffix = "*.mp3"
|
50 |
-
song_dir = "/data/bg-music"
|
51 |
-
files = glob.glob(os.path.join(song_dir, suffix))
|
52 |
-
return random.choice(files) if files else ""
|
53 |
-
|
54 |
-
if os.path.exists(bgm_file):
|
55 |
-
return bgm_file
|
56 |
-
|
57 |
-
return ""
|
58 |
-
|
59 |
-
def add_background_music(video_path, bgm_file, output_path="video_with_bgm.mp4"):
|
60 |
-
check_file_exists(video_path)
|
61 |
-
check_file_exists(bgm_file)
|
62 |
-
|
63 |
-
video = VideoFileClip(video_path)
|
64 |
-
bgm = AudioFileClip(bgm_file).subclip(0, video.duration)
|
65 |
-
final_audio = CompositeAudioClip([video.audio, bgm])
|
66 |
-
final_video = video.set_audio(final_audio)
|
67 |
-
final_video.write_videofile(output_path, audio_codec="aac")
|
68 |
-
return output_path
|
69 |
-
|
70 |
-
def combine_videos(combined_video_path: str,
|
71 |
-
video_paths: list[str],
|
72 |
-
audio_file: str,
|
73 |
-
max_clip_duration: int = 5,
|
74 |
-
threads: int = 2,
|
75 |
-
) -> str:
|
76 |
-
check_file_exists(audio_file)
|
77 |
-
|
78 |
-
audio_clip = AudioFileClip(audio_file)
|
79 |
-
audio_duration = audio_clip.duration
|
80 |
-
logger.info(f"Max duration of audio: {audio_duration} seconds")
|
81 |
-
|
82 |
-
clips = []
|
83 |
-
video_duration = 0
|
84 |
-
|
85 |
-
while video_duration < audio_duration:
|
86 |
-
random.shuffle(video_paths)
|
87 |
-
|
88 |
-
for video_path in video_paths:
|
89 |
-
check_file_exists(video_path)
|
90 |
-
clip = VideoFileClip(video_path).without_audio()
|
91 |
-
if (audio_duration - video_duration) < clip.duration:
|
92 |
-
clip = clip.subclip(0, (audio_duration - video_duration))
|
93 |
-
elif max_clip_duration < clip.duration:
|
94 |
-
clip = clip.subclip(0, max_clip_duration)
|
95 |
-
clip = clip.set_fps(30)
|
96 |
-
clips.append(clip)
|
97 |
-
video_duration += clip.duration
|
98 |
-
|
99 |
-
final_clip = concatenate_videoclips(clips)
|
100 |
-
final_clip = final_clip.set_fps(30)
|
101 |
-
logger.info(f"Writing combined video to {combined_video_path}")
|
102 |
-
final_clip.write_videofile(combined_video_path, threads=threads)
|
103 |
-
logger.success(f"Completed combining videos")
|
104 |
-
return combined_video_path
|
105 |
-
|
106 |
-
def generate_video(video_paths: list[str],
|
107 |
-
audio_path: str,
|
108 |
-
output_file: str,
|
109 |
-
) -> str:
|
110 |
-
logger.info(f"Start generating video")
|
111 |
-
combined_video_path = "temp_combined_video.mp4"
|
112 |
-
|
113 |
-
combine_videos(combined_video_path, video_paths, audio_path)
|
114 |
-
|
115 |
-
final_video = VideoFileClip(combined_video_path)
|
116 |
-
audio_clip = AudioFileClip(audio_path)
|
117 |
-
final_video = final_video.set_audio(audio_clip)
|
118 |
-
|
119 |
-
logger.info(f"Writing final video to {output_file}")
|
120 |
-
final_video.write_videofile(output_file, audio_codec="aac")
|
121 |
-
|
122 |
-
os.remove(combined_video_path)
|
123 |
-
logger.success(f"Completed generating video: {output_file}")
|
124 |
-
return output_file
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|