File size: 5,073 Bytes
1038d6b |
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 |
import cv2
import os
import shutil
import random
from tqdm import tqdm
[os.system(c) for c in ["clear", "cls", "color a"]]
DEFAULT_DYNAMIC_INTERVALS: list[list[float]] = [
[0.00, 9.44], [9.44, 12.07], [19.54, 22.04], [29.50, 31.14],
[39.50, 41.14], [49.57, 50.55], [59.44, 61.14],
]
POLA_INTERVAL: list[int] = [10, 10]
REAL_VIDEO_PATH = "assets/ppt_real.mp4"
REV_VIDEO_PATH = "assets/ppt_reverse.mp4"
OUTPUT_DIR = "results"
def get_video_duration(video_path: str) -> int | None:
"""
Membaca durasi file video menggunakan OpenCV dan mengembalikannya
sebagai integer dalam detik.
(TQDM dihilangkan dari sini untuk mempercepat pembacaan metadata awal)
"""
if not os.path.exists(video_path):
print(f"Error: File video tidak ditemukan di {video_path}")
return 0
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"Error: Tidak dapat membuka file video {video_path}")
return None
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
cap.release()
if fps == 0 or frame_count == 0:
print("Error: Tidak dapat mengambil FPS atau jumlah frame.")
return None
return int(frame_count / fps)
def extract_video_segment(input_path: str, output_path: str, start_sec: float, end_sec: float):
"""
Memotong segmen video dari input_path berdasarkan start_sec dan end_sec,
lalu menyimpannya ke output_path dengan progress bar.
"""
cap = cv2.VideoCapture(input_path)
if not cap.isOpened():
print(f"Error membuka video: {input_path}")
return
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'avc1') # type: ignore
writer = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) # type: ignore
start_frame = int(start_sec * fps)
end_frame = int(end_sec * fps)
total_frames_to_write = end_frame - start_frame
if total_frames_to_write <= 0:
print(f"Warning: Tidak ada frame untuk diekstrak untuk segmen {output_path}")
cap.release()
writer.release()
return
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
segment_pbar_desc = os.path.basename(output_path)
with tqdm(total=total_frames_to_write, desc=f"Mengekstrak {segment_pbar_desc}", unit="frame", leave=False) as pbar:
current_frame = start_frame
while current_frame < end_frame:
ret, frame = cap.read()
if not ret:
break
writer.write(frame)
pbar.update(1)
current_frame += 1
cap.release()
writer.release()
if len(os.listdir(OUTPUT_DIR)) > 0:
exit() if "n" in input("Lanjutkan proses? [N] ").lower() else ""
shutil.rmtree(OUTPUT_DIR)
os.makedirs(OUTPUT_DIR, exist_ok=True)
print(f"Direktori output dipastikan ada: '{OUTPUT_DIR}'")
REAL_VIDEO_DURATION = get_video_duration(REAL_VIDEO_PATH) or 0
REV_VIDEO_DURATION = get_video_duration(REV_VIDEO_PATH) or 0
LONG_DURATION = max(REAL_VIDEO_DURATION, REV_VIDEO_DURATION)
print(f"Durasi video terpanjang (LONG_DURATION): {LONG_DURATION} detik")
dynamicIntervals: list[list[float]] = DEFAULT_DYNAMIC_INTERVALS.copy()
lastSecond = dynamicIntervals[-1][1] if dynamicIntervals else 0.0
with tqdm(total=LONG_DURATION, initial=lastSecond, desc="Membuat Interval", unit="s") as pbar:
while lastSecond < LONG_DURATION:
previous_lastSecond = lastSecond
lastInterval = dynamicIntervals[-1]
step = random.uniform(5.0, 10.0)
new_start_time: float = lastInterval[0] + POLA_INTERVAL[0]
new_end_time: float = lastInterval[1] + POLA_INTERVAL[1]
if new_start_time >= LONG_DURATION:
break
lastSecond = min(new_end_time, LONG_DURATION)
dynamicIntervals.append([
new_start_time, lastSecond
])
increment = lastSecond - previous_lastSecond
pbar.update(increment)
reverseDynamicIntervals: list[list[float]] = []
for start, end in dynamicIntervals:
rev_start = round(LONG_DURATION - end, 2)
rev_end = round(LONG_DURATION - start, 2)
reverseDynamicIntervals.append([rev_start, rev_end])
print(f"Total {len(dynamicIntervals)}, {len(reverseDynamicIntervals)} interval dinamis dibuat.")
print("\nMemproses segmen video REAL...")
for idx, interval in enumerate(tqdm(dynamicIntervals, desc="Video REAL")):
start_time, end_time = interval
output_filename = os.path.join(OUTPUT_DIR, f"real_{idx}.mp4")
extract_video_segment(REAL_VIDEO_PATH, output_filename, start_time, end_time)
print("\nMemproses segmen video REVERSE...")
for idx, interval in enumerate(tqdm(reverseDynamicIntervals, desc="Video REVERSE")):
start_time, end_time = interval
output_filename = os.path.join(OUTPUT_DIR, f"reverse_{idx}.mp4")
extract_video_segment(REV_VIDEO_PATH, output_filename, start_time, end_time)
print("\n\nSemua proses ekstraksi video telah selesai.") |