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
|