Agung1453's picture
Update app.py
f741a15 verified
import gradio as gr
import os
import shutil
import subprocess
import time
from datetime import datetime, timedelta
# Fungsi untuk mendapatkan durasi video
def get_video_duration(input_path):
cmd = [
"ffprobe",
"-v", "error",
"-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1",
input_path
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
duration = float(result.stdout.strip())
if duration <= 0:
raise ValueError("Durasi video tidak valid atau nol.")
return duration
except (subprocess.CalledProcessError, ValueError) as e:
# Log error untuk debugging
error_msg = f"Gagal mendapatkan durasi: {str(e)}\nSTDERR: {result.stderr if 'result' in locals() else 'Tidak ada output'}"
with open("/tmp/ffprobe_error.log", "w") as f:
f.write(error_msg)
return 0 # Fallback ke 0 jika gagal
# Fungsi untuk memproses video dengan FFmpeg dan memantau progres
def process_video(fileobj):
# Direktori untuk menyimpan file
UPLOAD_FOLDER = "/tmp/uploads"
OUTPUT_FOLDER = "/tmp/outputs"
PROGRESS_FILE = "/tmp/progress.txt"
# Buat direktori jika belum ada
for folder in [UPLOAD_FOLDER, OUTPUT_FOLDER]:
if not os.path.exists(folder):
os.makedirs(folder)
# Simpan file yang diunggah
input_path = os.path.join(UPLOAD_FOLDER, os.path.basename(fileobj.name))
shutil.copyfile(fileobj.name, input_path)
# Path untuk file output
output_filename = "output_video.mp4"
output_path = os.path.join(OUTPUT_FOLDER, output_filename)
# Dapatkan durasi video
duration = get_video_duration(input_path)
if duration == 0:
# Fallback: Lanjutkan tanpa durasi, progres tidak akan akurat
yield f"Peringatan: Tidak dapat membaca durasi video. Progres tidak akan ditampilkan.", None, None
duration = float("inf") # Hindari pembagian nol
# Perintah FFmpeg untuk frame interpolation
ffmpeg_cmd = [
"ffmpeg",
"-y", # Overwrite file output
"-i", input_path,
"-vf", "minterpolate=fps=60:mi_mode=mci:mc_mode=aobmc:vsbmc=1:me_mode=bidir",
"-c:v", "libx264",
"-preset", "fast",
"-c:a", "copy",
"-progress", PROGRESS_FILE,
output_path
]
try:
# Jalankan FFmpeg sebagai proses terpisah
process = subprocess.Popen(ffmpeg_cmd, stderr=subprocess.PIPE, universal_newlines=True)
start_time = time.time()
progress_percent = 0
eta = "Menghitung..."
# Pantau progres secara real-time
while process.poll() is None:
if duration == float("inf"):
# Jika durasi tidak tersedia, tampilkan progres tanpa persentase
elapsed_time = time.time() - start_time
yield f"Progres: Sedang memproses... | Waktu Berjalan: {str(timedelta(seconds=int(elapsed_time)))}", None, None
elif os.path.exists(PROGRESS_FILE):
with open(PROGRESS_FILE, "r") as f:
lines = f.readlines()
for line in lines:
if "out_time_ms=" in line:
out_time_ms = float(line.split("=")[1]) / 1_000_000 # Konversi ke detik
progress_percent = min((out_time_ms / duration) * 100, 100)
elapsed_time = time.time() - start_time
if progress_percent > 0:
total_estimated_time = elapsed_time / (progress_percent / 100)
eta_seconds = total_estimated_time - elapsed_time
eta = str(timedelta(seconds=int(eta_seconds)))
else:
eta = "Menghitung..."
yield f"Progres: {progress_percent:.1f}% | Estimasi Selesai: {eta}", None, None
time.sleep(1) # Jeda untuk mengurangi beban CPU
# Periksa apakah proses berhasil
if process.returncode == 0:
yield f"Progres: 100% | Selesai!", output_path, output_path
else:
stderr_output = process.communicate()[1]
yield f"Error FFmpeg: {stderr_output}", None, None
except Exception as e:
yield f"Error: {str(e)}", None, None
finally:
# Bersihkan file sementara
for file_path in [input_path, PROGRESS_FILE]:
if os.path.exists(file_path):
os.remove(file_path)
# Antarmuka Gradio
with gr.Blocks() as demo:
gr.Markdown("# Frame Interpolation dengan FFmpeg")
gr.Markdown("Unggah video untuk meningkatkan frame rate menjadi 60 FPS menggunakan FFmpeg.")
with gr.Row():
with gr.Column():
upload_button = gr.UploadButton(
"Unggah Video",
file_types=["video"],
file_count="single"
)
with gr.Column():
progress_text = gr.Textbox(label="Status Proses")
preview = gr.Video(label="Preview Video Hasil")
download_button = gr.File(label="Unduh Video Hasil")
# Hubungkan upload dengan fungsi pemrosesan
upload_button.upload(
process_video,
inputs=upload_button,
outputs=[progress_text, preview, download_button]
)
# Jalankan aplikasi
if __name__ == "__main__":
demo.launch()