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()