def create_video_from_frames(
    frames_dir: str,
    frame_rate: Optional[int] = None,
    sound_path: Optional[str] = None,
    output_dir: Optional[str] = None,
    output_mime_type: Optional[str] = None,
):
    """
    Create a video from frames and save it to the output_path. This needs FFmpeg installed.
    """
    if not os.path.exists(frames_dir):
        raise "frames_dir does not exist"
    frames_dir = os.path.normpath(frames_dir)

    if output_dir is None:
        output_dir = OUTPUTS_VIDEOS_DIR
    os.makedirs(output_dir, exist_ok=True)

    frame_img_mime_type = ".png"
    pix_format = "yuv420p"
    vid_codec, audio_codec = "libx264", "aac"

    if output_mime_type is None:
        output_mime_type = ".mp4"

    output_mime_type = output_mime_type.lower()
    if output_mime_type == ".mov":
        pix_format = "yuva444p10le"
        vid_codec, audio_codec = "prores_ks", "aac"

    elif output_mime_type == ".webm":
        pix_format = "yuva420p"
        vid_codec, audio_codec = "libvpx-vp9", "libvorbis"

    elif output_mime_type == ".gif":
        pix_format = None
        vid_codec, audio_codec = "gif", None

    output_path = get_auto_incremental_file_path(output_dir, output_mime_type.replace(".", ""))

    if sound_path is None:
        temp_sound = os.path.normpath(os.path.join(TEMP_VIDEO_FRAMES_DIR, "sound.mp3"))
        if os.path.exists(temp_sound):
            sound_path = temp_sound

    if frame_rate is None:
        frame_rate = 25  # Default frame rate for ffmpeg

    command = [
        'ffmpeg',
        '-loglevel', 'error',
        '-y',
        '-framerate', str(frame_rate),
        '-i', os.path.join(frames_dir, f"%05d{frame_img_mime_type}"),
        '-c:v', vid_codec,
        '-vf', 'crop=trunc(iw/2)*2:trunc(ih/2)*2' if pix_format else None,
    ]

    if output_mime_type == ".gif":
        command += [
            "-filter_complex", "[0:v] palettegen=reserve_transparent=on [p]; [0:v][p] paletteuse",
            "-loop", "0"
        ]
    else:
        command += [
            '-pix_fmt', pix_format
        ]

    command += [output_path]

    if output_mime_type != ".gif" and sound_path is not None:
        command += [
            '-i', sound_path,
            '-c:a', audio_codec,
            '-strict', 'experimental',
            '-b:a', '192k',
            '-shortest'
        ]
    try:
        subprocess.run(command, check=True)
    except subprocess.CalledProcessError as e:
        print(f"Error occurred while creating video from frames")
        raise
    return output_path

    Create a video from frames and save it to the output_path. This needs FFmpeg installed.
    
modules/utils/video_helper.py