File size: 18,464 Bytes
5fa5566
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import base64
import os
import re
import subprocess
from pathlib import Path
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from ffmpeg_progress_yield import FfmpegProgress
from tqdm import tqdm

import file_utils


def insert_subtitle(input_media_path: Path, subtitles_path: [Path], burn_subtitles: bool, output_video_path: Path, codec_video: str = "h264", codec_audio: str = "aac"):
    # use only valid srt files
    subtitles_path: [Path] = file_utils.validate_files(subtitles_path)

    # insert in comand the basics of ffmpeg
    cmd_ffmpeg = ["ffmpeg", "-y"]
    cmd_ffmpeg_input_map = []

    # add ffmpeg input main media
    cmd_ffmpeg.extend(["-i", "file:" + input_media_path.as_posix()])
    # map video stream, audio, subtitle, data and metadata
    map_index = cmd_ffmpeg.count("-i") - 1
    cmd_ffmpeg_input_map.extend(["-map", f"{map_index}:V?", "-map", f"{map_index}:a",
                                 "-ignore_unknown"])

    # detect if input has video channels
    result: str = subprocess.run(["ffprobe", "-i", "file:" + input_media_path.as_posix(), "-show_streams",
                                 "-select_streams", "V", "-loglevel", "error"], capture_output=True, text=True).stdout
    no_video = True if result is None or "DISPOSITION:attached_pic=0" not in result else False

    # if input has no video channels, map a 1280x720 black screen
    if no_video:
        # create a background image if media is only audio
        background_tempfile: file_utils.TempFile = file_utils.TempFile(
            "", ".jpeg")

        # create a 1280x720 jpeg image
        with open(file=background_tempfile.getpath(), mode="wb") as file:
            file.write(base64.b64decode("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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/EACAQAAMBAAICAgMAAAAAAAAAAAABERAgMEFgMXBAkND/2gAIAQEAAQUC/QFPoKE7JzQ+p9MJzhPb7jITITIQgljRCEyY8SGTITIeYQmQg8Q9hNpRkITIT2ZbCY2LX1IYh4hi+HrzyLEPHiHi3yLHw8iH7S8Ysg8nB5MWvFrJjzyLFrxasnF5MXyIfx7NfwL0XheaJj6rwv0hS/0nf//EABQRAQAAAAAAAAAAAAAAAAAAALD/2gAIAQMBAT8BYQ//xAAUEQEAAAAAAAAAAAAAAAAAAACw/9oACAECAQE/AWEP/8QAFBABAAAAAAAAAAAAAAAAAAAA0P/aAAgBAQAGPwJhA//EACMQAAMBAQACAwABBQAAAAAAAAABERAxQVEgIWAwQGFwkND/2gAIAQEAAT8h/wBAVf4BSuX/AEelESX8NOv4VQ4+SV/X67jgTovkSTLX3FiBqCogfoUWQQhAwlSBKHGUQkFSGoIQNQgnGYHAlSMpM4OcSpGJ9zGYGTFRA/QSrzA1P0vWPomY4FwgfZ3Ep5OBWdI73E/uZb9ZHe55DQanGcnOHRaT0yvPwtWPhwNBOrfBznA1fIh8Z9OlpxkfvEfA1OP0yd1qLh2NGdII8C4dXPOcCdIGkhs4cb7nRAlPj9D4N4+PjW8DVIH36E6RPGonUQyJYPn6mUW5XtaK8sKyvblbWUu0XLCsr95X7yv2Imf2MSi3Sv2V+8rK3tF2tr95f+mB/wD/2gAMAwEAAgADAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIBCADCBACCMBCBACCCBCJBADIDCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFLHGEGHHMMBABNBJKPAHKFCBHJHOKFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAMEMAAAEIAAEAIIMBAEIMAEAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAALD/2gAIAQMBAT8QYQ//xAAUEQEAAAAAAAAAAAAAAAAAAACw/9oACAECAQE/EGEP/8QAJxABAAIBAwQBBQADAAAAAAAAAQARMRAhYUFRcZFgIDBwgbGQodD/2gAIAQEAAT8Q/wAAQxcRGn8ALwJTuzsMx9u1Z+srWRSh9kCWMQ7fs1LupVu7+peBKd2PYxKaflgsHeBRRBVBcAWTBCg2wHVlMgTO8W4jveZjiccrL9IFjegWFy8tnHKyzERUQLmCmusz6BY3mCCrhAqw0Be8Gt92ccv8QqyxPBEVssO1cqWYl/iccpedoNavfT+8wedHe0C5iU22lt6BRRNzY2hVvsygTMzHYnHNm/SFQxHRZxzOMfJcOgRDALKiC1Jj8SxQRWLMRShqJlaG/GF9A8TaLjxo5gq9FsQVemR61oK/aog26xbX0mfTL5mDzMEdFgBYy5dhKdlfaGCOlaGZ/ExxaVGsZgaf3mDzofeJhSBClubE0Q3CAFkzwKKijZXQUotJ7EW1zP8AJjHMQcgzBLVGCY/Ew+JkMMQFOIF0vzKNhvEIqIbGZg1fmCJZAFgLuALIs3ArSEKPWIJSQDYbTPoskQFJCjY6TFcMof7ncXEUHWGCOn+cz+IZu/UQcl6YGn99Sq36g5SkxEdgIY5iy0gAbbEtUYIXIRRcRWk3Rl8TJmb5NicsVk6UdX3FXLehgMW66CwYtllHV96CmGopyrBTDU5Yq5b0CwxS2rFOV15Za7tirluCwZyzM5HuW3d7zke4KYanI9y0tbiq3P2zaItw7aCMKTke5yPegXWOQ68sU5dLrE5Yq5bgphqcj3BTCkU5X3+ChRsgupFOCpn/AKTt/9k="))

        # get input media duration
        duration_sec = subprocess.run(["ffprobe", "-i", "file:" + input_media_path.as_posix(), "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=p=0"],
                                      capture_output=True, text=True).stdout.split("\n")[0].split('.')[0]

        cmd_ffmpeg.extend(["-t", f"{duration_sec}", "-loop", "1",
                          "-framerate", "10", "-i", background_tempfile.getpath().as_posix()])
        map_index = cmd_ffmpeg.count("-i") - 1
        # unmap #0, remap #0 with no video, map #1 (generated video from image)
        cmd_ffmpeg_input_map.extend(
            ["-map", "-0", "-map", f"0:a", "-map", f"0:d?", "-map", f"0:t?", "-map", f"{map_index}:V", "-ignore_unknown"])

    # map each subtitle
    for i, subtitle in enumerate(subtitles_path):
        cmd_ffmpeg.extend(["-i", "file:" + subtitle.as_posix()])
        map_index = cmd_ffmpeg.count("-i") - 1
        cmd_ffmpeg_input_map.extend(["-map", f"{map_index}:s"])

    # add comand to burn subtitles if its demanded and has at least one valid subtitle in the array. Burn the first one. Also ensure hwupload if necessary
    vf_hwupload = True if codec_video.endswith(
        ("_nvenc", "_amf", "_v4l2m2m", "_qsv", "_vaapi", "_videotoolbox", "_cuvid")) else False
    hw_device = codec_video.split("_")[-1] if vf_hwupload else None
    # set hw_device as cuda if api is nvenc or cuvid
    if hw_device == "nvenc" or hw_device == "cuvid":
        hw_device = "cuda"
        vf_hwupload = False

    # set hw_device as vaapi if api is v4l2m2m or amf
    if hw_device == "v4l2m2m" or hw_device == "amf":
        hw_device = "vaapi"

    if burn_subtitles and len(subtitles_path) > 0:
        # create temp file for .srt
        srt_temp = file_utils.TempFile(
            "", file_ext=".srt")

        file_utils.copy_file_if_different(
            subtitles_path[0], srt_temp.getpath(), True)

        # align subtitles to botton center if hass video and to center center if only audio with black screen
        sub_align = 10 if no_video else 2

        # insert scale, subtitles filter and hwupload if required
        # scale at minimul height of 480p. it also will make the dimensions divisible by 2
        cmd_ffmpeg.extend(
            ["-vf", f"format=nv12, scale='ceil((max(480,ih)*iw/ih)/2)*2:ceil(max(480,ih)/2)*2', subtitles=\'{add_ffmpeg_escape_chars(srt_temp.temp_file.name)}\':force_style='Alignment={sub_align},Fontname=Jost,PrimaryColour=&H03fcff,Fontsize=18,BackColour=&H80000000,Bold=1,Spacing=0.09,Outline=1,Shadow=0,MarginL=10,MarginR=10'" + (', hwupload' if vf_hwupload else '')])
    else:
        if vf_hwupload:
            cmd_ffmpeg.extend(["-vf", f"format=nv12, hwupload"])
        burn_subtitles = False

    cmd_ffmpeg.extend(cmd_ffmpeg_input_map)

    # init a hw_device if hwupload is set on video filters
    if hw_device is not None:
        cmd_ffmpeg.extend(["-init_hw_device", hw_device])

    # add the remaining parameters and output path
    cmd_ffmpeg.extend(["-c:V", codec_video, "-c:a", codec_audio, "-c:s", "mov_text",
                        "-pix_fmt", "yuv420p", "-movflags", "+faststart",
                       "-sws_flags", "bicubic+accurate_rnd+full_chroma_int+full_chroma_inp",
                       "file:" + output_video_path.as_posix()])

    # run FFmpeg command with a fancy progress bar
    ff = FfmpegProgress(cmd_ffmpeg)
    with tqdm(total=100, position=0, ascii="β–‘β–’β–ˆ", desc="Inserting subtitles" if not burn_subtitles else "Burning subtitles", unit="%", unit_scale=True, leave=True, bar_format="{desc} [{bar}] {percentage:3.0f}% | {rate_fmt}{postfix} | ETA: {remaining} | ⏱: {elapsed}") as pbar:
        for progress in ff.run_command_with_progress():
            pbar.update(progress - pbar.n)

    # destroy unecessary file
    if 'srt_temp' in locals():
        srt_temp.destroy()


def extract_audio_wav(input_media_path: Path, output_path: Path):
    # set the FFMpeg command
    cmd_ffmpeg = ["ffmpeg", "-y", "-i", "file:" + input_media_path.as_posix(),
                  "-vn", "-c:a", "pcm_s16le", "-ac", "1", "-ar", "16000", "file:" + output_path.as_posix()]

    # run FFmpeg command with a fancy progress bar
    ff = FfmpegProgress(cmd_ffmpeg)
    with tqdm(total=100, position=0, ascii="β–‘β–’β–ˆ", desc="Extracting audio", unit="%", unit_scale=True, leave=True, bar_format="{desc} {percentage:3.0f}% | ETA: {remaining} | ⏱: {elapsed}") as pbar:
        for progress in ff.run_command_with_progress():
            pbar.update(progress - pbar.n)


def extract_short_wav(input_media_path: Path, output_path: Path):
    # get input media duration
    duration_sec = subprocess.run(["ffprobe", "-i", "file:" + input_media_path.as_posix(), "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=p=0"],
                                  capture_output=True, text=True).stdout.split("\n")[0].replace("\n", "").replace(" ", "").replace("   ", "").replace("00:", "").replace(":", "").split(".")[0]

    if int(duration_sec) > 240:
        start_sec = int(duration_sec) - 120
        end_sec = int(duration_sec) - 60
    elif int(duration_sec) > 120:
        start_sec = int(duration_sec) - 80
        end_sec = int(duration_sec) - 20
    elif int(duration_sec) > 80:
        start_sec = int(duration_sec) - 60
        end_sec = int(duration_sec) - 20
    else:
        start_sec = 0
        end_sec = int(duration_sec)

    # set the FFMpeg command
    cmd_ffmpeg = ["ffmpeg", "-y", "-ss", f"{start_sec}", "-t", f"{end_sec}",  "-i", "file:" + input_media_path.as_posix(),
                  "-vn", "-c:a", "pcm_s16le", "-af", "loudnorm", "-ac", "1", "-ar", "16000", "file:" + output_path.as_posix()]

    # run FFmpeg command with a fancy progress bar
    ff = FfmpegProgress(cmd_ffmpeg)
    with tqdm(total=100, position=0, ascii="β–‘β–’β–ˆ", desc="Extracting audio", unit="%", unit_scale=True, leave=False, bar_format="{desc} {percentage:3.0f}% | ETA: {remaining} | ⏱: {elapsed}") as pbar:
        for progress in ff.run_command_with_progress():
            pbar.update(progress - pbar.n)


def add_ffmpeg_escape_chars(string):
    new_string = ""
    for char in string:
        if os.name == 'nt':
            if char == ":" or char == "\x5c":
                new_string += "\x5c"
        new_string += char
    return new_string