from moviepy import * import pysrt import gradio as gr def time_to_seconds(time_obj): return time_obj.hours * 3600 + time_obj.minutes * 60 + time_obj.seconds + time_obj.milliseconds / 1000 def create_subtitle_clips(subtitles, videosize, fontsize, font, color, debug): subtitle_clips = [] color_clips=[] for subtitle in subtitles: start_time = time_to_seconds(subtitle.start) # Add 2 seconds offset end_time = time_to_seconds(subtitle.end) duration = end_time - start_time video_width, video_height = videosize max_width = video_width * 0.8 max_height = video_height * 0.2 #reshaped_text = arabic_reshaper.reshape(subtitle.text) #bidi_text = get_display(reshaped_text) text_clip = TextClip(font, subtitle.text, font_size=fontsize, size=(int(video_width * 0.8), int(video_height * 0.2)) ,text_align="center" ,color=color, method='caption').with_start(start_time).with_duration(duration) #myclip = ColorClip(size=(int(video_width * 0.8), int(video_height * 0.2)) , color=(225, 0, 0)).with_opacity(0.2).with_start(start_time).with_duration(duration) subtitle_x_position = 'center' subtitle_y_position = video_height * 0.68 text_position = (subtitle_x_position, subtitle_y_position) subtitle_clips.append(text_clip.with_position(text_position)) #color_clips.append(myclip.with_position(text_position)) return subtitle_clips import subprocess import os # Mapping of color names to FFmpeg-compatible hex codes COLOR_MAP = { 'white': '#FFFFFF', 'yellow': '#FFFF00', 'red': '#FF0000', 'green': '#00FF00', 'blue': '#0000FF', 'black': '#000000' } def hex_to_ffmpeg_color(hex_code): """ Convert standard hex color (#RRGGBB) to FFmpeg's PrimaryColour format (&HBBGGRR&). Args: hex_code (str): Standard hex color code (e.g., '#FFFFFF') Returns: str: FFmpeg color code (e.g., '&HFFFFFF&') """ hex_code = hex_code.lstrip('#') r, g, b = hex_code[0:2], hex_code[2:4], hex_code[4:6] return f'&H{b}{g}{r}&' def video_edit(srt, input_video, font_color, font_type, font_size, input_audio=None): """ Burns subtitles into a video using FFmpeg with customizable styling. Args: srt (str): Path to SRT subtitle file input_video (dict or str): Input video path or dict with 'video' key font_color (str): Color name (e.g., 'white', 'yellow') font_type (str): Font name for subtitles font_size (int): Font size for subtitles input_audio (str, optional): Path to audio file (if provided) Returns: str: Path to output video file """ # Handle input_video as dict or string if isinstance(input_video, dict): video_path = input_video.get('video', '') else: video_path = input_video # Validate input if not video_path or not os.path.exists(video_path): raise ValueError("Invalid or missing video file") if not os.path.exists(srt): raise ValueError("Subtitle file not found") # Generate output filename input_base = os.path.splitext(video_path)[0] output_video = f"{input_base}_subtitled.mp4" print(font_color, font_type) # Convert color name to FFmpeg format hex_color = COLOR_MAP.get(font_color.lower()) if not hex_color: raise ValueError(f"Unsupported color: {font_color}. Supported colors: {', '.join(COLOR_MAP.keys())}") ffmpeg_color = hex_to_ffmpeg_color(hex_color) print(ffmpeg_color) # Build subtitle style subtitle_style = f"FontName={font_type},FontSize={font_size},PrimaryColour={ffmpeg_color}" fonts_dir = os.path.dirname(srt) # Construct FFmpeg command cmd = [ 'ffmpeg', '-i', video_path, # Input video ] # Add audio input if provided (though we'll still keep original audio) if input_audio and os.path.exists(input_audio): cmd.extend(['-i', input_audio]) cmd.extend([ '-vf', f"subtitles={srt}:fontsdir={fonts_dir}:force_style='{subtitle_style}'", # Burn subtitles '-c:v', 'libx264', # Video codec '-c:a', 'copy', # Always copy original audio '-r', '24', # Frame rate '-preset', 'ultrafast',# Encoding preset '-y', # Overwrite output output_video ]) # Execute FFmpeg command try: subprocess.run(cmd, check=True, stderr=subprocess.PIPE, universal_newlines=True) except subprocess.CalledProcessError as e: raise RuntimeError(f"FFmpeg failed: {e.stderr}") print(f"Video processed successfully: {output_video}") return output_video with gr.Blocks() as demo: gr.Markdown("Start typing below and then click **Run** to see the progress and final output.") with gr.Column(): srt_file = gr.File() video_in = gr.Video() color = gr.Text() font = gr.Text() font_size = gr.Number() audio_in = gr.Audio(type = "filepath") btn = gr.Button("Create") output_video = gr.Video() btn.click( fn=video_edit, inputs=[srt_file, video_in, color, font, font_size, audio_in], outputs=output_video ) demo.launch(debug=True)