Spaces:
Sleeping
Sleeping
import gradio as gr | |
import moviepy.editor as mp | |
import os | |
from PIL import Image | |
def process_video(video_file, start_time, end_time, resolution, fps, playback_speed, loop_count): | |
# 로그 출력: 파일 업로드 확인 | |
print("파일 업로드 완료:", video_file.name) | |
# 동영상 불러오기 | |
video = mp.VideoFileClip(video_file.name) | |
duration = video.duration | |
print("동영상 길이:", duration) | |
# 시작/끝 시간 처리 | |
start_time = float(start_time) if start_time else 0 | |
end_time = float(end_time) if end_time else duration | |
print(f"시작 시간: {start_time}, 끝 시간: {end_time}") | |
# 영상 클립 추출 | |
trimmed_clip = video.subclip(start_time, end_time) | |
# 해상도 조정 | |
if resolution != "원본": | |
width, height = [int(i) for i in resolution.split("x")] | |
trimmed_clip = trimmed_clip.resize(height=height) | |
print("해상도 조정:", resolution) | |
else: | |
print("해상도 유지: 원본") | |
# 프레임 속도 조정 | |
trimmed_clip = trimmed_clip.set_fps(fps) | |
print("프레임 속도 조정:", fps) | |
# 재생 속도 조정 | |
trimmed_clip = trimmed_clip.fx(mp.vfx.speedx, playback_speed) | |
print("재생 속도 조정:", playback_speed) | |
# GIF 반복 횟수 | |
loop_count = "infinite" if loop_count == 0 else loop_count | |
print("GIF 반복 횟수 설정:", loop_count) | |
# 썸네일 생성 | |
start_thumb = trimmed_clip.get_frame(0) | |
end_thumb = trimmed_clip.get_frame(end_time - start_time) | |
start_thumbnail = Image.fromarray(start_thumb) | |
end_thumbnail = Image.fromarray(end_thumb) | |
# GIF 저장 | |
gif_path = "output.gif" | |
trimmed_clip.write_gif(gif_path, loop=loop_count) | |
print("GIF 생성 완료:", gif_path) | |
return start_thumbnail, end_thumbnail, gif_path | |
def preview_gif(gif_path): | |
return gif_path | |
# Gradio 인터페이스 구성 | |
with gr.Blocks() as app: | |
gr.Markdown("## 동영상을 GIF로 변환하는 툴") | |
# 동영상 업로드 | |
video_input = gr.Video(label="동영상 업로드") | |
# 동영상 재생 및 정보 출력 | |
video_output = gr.Video(label="업로드된 동영상 미리보기") | |
video_info = gr.Label(label="동영상 정보") | |
# 입력창: 시작 시간, 끝 시간 | |
start_time = gr.Textbox(label="시작 시간 (초 단위)", placeholder="예: 5.0") | |
end_time = gr.Textbox(label="끝 시간 (초 단위)", placeholder="예: 10.0") | |
# 썸네일 출력 | |
start_thumbnail_output = gr.Image(label="시작 지점 썸네일") | |
end_thumbnail_output = gr.Image(label="끝 지점 썸네일") | |
# 해상도 조절 슬라이더 | |
resolution_slider = gr.Dropdown( | |
choices=["원본", "1920x1080", "1280x720", "640x480"], | |
value="원본", | |
label="해상도 선택" | |
) | |
# 프레임 속도 조절 슬라이더 | |
fps_slider = gr.Slider(1, 60, step=1, value=30, label="프레임 속도 (기본 30fps)") | |
# 재생 속도 조절 슬라이더 | |
playback_speed_slider = gr.Slider(0.1, 4.0, step=0.1, value=1.0, label="재생 속도 (기본 1배속)") | |
# GIF 반복 횟수 조절 슬라이더 | |
loop_count_slider = gr.Slider(0, 10, step=1, value=0, label="GIF 반복 횟수 (0은 무한 반복)") | |
# GIF 생성 버튼 | |
generate_button = gr.Button("GIF 생성") | |
# GIF 미리보기 및 다운로드 출력 | |
gif_preview_output = gr.Image(label="GIF 미리보기") | |
gif_download_output = gr.File(label="GIF 다운로드") | |
# 동영상 처리 함수 연결 | |
video_input.change( | |
lambda video_file: (video_file, {"동영상 길이(초)": mp.VideoFileClip(video_file.name).duration}), | |
inputs=[video_input], | |
outputs=[video_output, video_info] | |
) | |
generate_button.click( | |
process_video, | |
inputs=[ | |
video_input, start_time, end_time, resolution_slider, | |
fps_slider, playback_speed_slider, loop_count_slider | |
], | |
outputs=[start_thumbnail_output, end_thumbnail_output, gif_download_output] | |
) | |
gif_preview_output.change(preview_gif, inputs=[gif_download_output], outputs=[gif_preview_output]) | |
# 앱 실행 | |
app.launch() | |