def do_encode(filtered): """Compression with x264""" print("Qpfile generating") vrf.gk(SRC_CUT, QPFILE) print("\n\n\nVideo encode") vrf.encode(filtered, X264, OUTPUT, **X264_ARGS) print("\n\n\nAudio extraction") eac3to_args = ['eac3to', SRC, '2:', A_SRC, '-log=NUL'] vrf.subprocess.run(eac3to_args, text=True, check=True, encoding='utf-8') print("\n\n\nAudio cut") eztrim(SRC_CLIP, (FRAME_START, FRAME_END), A_SRC, mkvextract_path="mkvextract") print("\n\n\nAudio encode") qaac_args = ['qaac64', A_SRC_CUT, '-V', '127', '--no-delay', '-o', A_ENC_CUT] vrf.subprocess.run(qaac_args, text=True, check=True, encoding='utf-8') print("\nFinal mux") mkv = MKVFile() mkv.add_track(MKVTrack(OUTPUT, language="jpn", default_track=True)) mkv.add_track(MKVTrack(A_ENC_CUT, language="jpn", default_track=True)) mkv.chapters(CHAPTER, "jpn") mkv.mux(OUTPUT_FINAL)
def do_encode(filtered): """Compression with x264""" print('Qpfile generating') vrf.gk(SRC_CUT, QPFILE) print('\n\n\nVideo encode') vrf.encode(filtered, X264, OUTPUT, **X264_ARGS) print('\n\n\nAudio extraction') eac3to_args = ['eac3to', SRC, '2:', A_SRC, '-log=NUL'] vrf.subprocess.run(eac3to_args, text=True, check=True, encoding='utf-8') print('\n\n\nAudio cut') eztrim(SRC_CLIP, (FRAME_START, FRAME_END), A_SRC, mkvextract_path='mkvextract') print('\n\n\nAudio encode') flac_args = ['flac', A_SRC_CUT, '-8'] vrf.subprocess.run(flac_args, text=True, check=True, encoding='utf-8') print('\nFinal mux') mkv = MKVFile() mkv.add_track(MKVTrack(OUTPUT, language='jpn', default_track=True)) mkv.add_track( MKVTrack(A_SRC_CUT[:-3] + 'flac', language='jpn', default_track=True)) mkv.mux(OUTPUT_FINAL)
def do_encode(filtered): """Compression with x264""" print('Qpfile generating') vdf.gk(SRC_CUT, QPFILE) print('\n\n\nVideo encode') vdf.encode(filtered, X264, OUTPUT, **X264_ARGS) print('\n\n\nAudio extraction') mka = MKVFile() mka.add_track(MKVTrack(SRC, 1)) mka.mux(A_SRC) print('\n\n\nAudio cut') eztrim(SRC_CLIP, (FRAME_START, FRAME_END), A_SRC, mkvextract_path='mkvextract') print('\n\n\nAudio encode') qaac_args = [ 'qaac64', A_SRC_CUT, '-V', '127', '--no-delay', '-o', A_ENC_CUT ] vdf.subprocess.run(qaac_args, text=True, check=True, encoding='utf-8') print('\nFinal mux') mkv = MKVFile() mkv.add_track(MKVTrack(OUTPUT, language='jpn', default_track=True)) mkv.add_track(MKVTrack(A_ENC_CUT, language='jpn', default_track=True)) mkv.chapters(CHAPTER, 'jpn') mkv.mux(OUTPUT_FINAL)
def batch_mux_files(mkv_list_1, mkv_list_2, settings_1, settings_2, output_directory): if len(mkv_list_1) == len(mkv_list_2): for item_num in range(0, len(mkv_list_1)): mkv = MKVfile() # Add tracks from source 1 mkv_file_1 = MKVfile(mkv_list_1[item_num]) track_list_1 = mkv_file_1.get_track() for track_number in settings_1: mkv.add_track(track_list_1[track_number]) mkv_file_2 = MKVfile(mkv_list_2[item_num]) track_list_2 = mkv_file_2.get_track() for track_number in settings_2: mkv.add_track(track_list_2[track_number]) output_name = mkv_list_1[item_num].split("/")[-1] logger.debug("Output directory is: " + output_directory + "/" + output_name) mkv.mux(output_directory + "/" + output_name) else: logger.error("Source 1 and Source 2 directory have different numbers of files. Unable to batch mux.") pass
def mux(fn, out): mkv = MKVFile(fn) addAudio(mkv, "AAC") addAudio(mkv, "MP3") addAudio(mkv, "DTS") addAudio(mkv, "Opus") addAudio(mkv, "FLAC") addAudio(mkv, "TrueHD Atmos") addAudio(mkv, "AC-3") addAudio(mkv, "DTS-HD Master Audio") addSubs(mkv, "sup") addSubs(mkv, "srt") addSubs(mkv, "ass") mkv.mux(out) #clean up print("Cleaning...") delete_by_extension("AAC") delete_by_extension("MP3") delete_by_extension("DTS") delete_by_extension("Opus") delete_by_extension("FLAC") delete_by_extension("TrueHD Atmos") delete_by_extension("AC-3") delete_by_extension("DTS-HD Master Audio") delete_by_extension("sup") delete_by_extension("srt") delete_by_extension("ass") print("KTHXBYE")
def do_encode(filtered): """Compression with x264""" print('Qpfile generating') vdf.gk(JPBD.src_cut, JPBD.qpfile) print('\n\n\nVideo encoding') vdf.encode(filtered, X264, JPBD.output, **X264_ARGS) print('\n\n\nAudio extraction') track_01 = USBD.a_src + '_eng.w64' track_02 = USBD.a_src + '_jpn.w64' eac3to_args = ['eac3to', USBD.src, '3:', track_01, '4:', track_02, '-log=NUL'] vdf.subprocess.run(eac3to_args, text=True, check=True, encoding='utf-8') mka = MKVFile() mka.add_track(MKVTrack(track_01, 0)) mka.add_track(MKVTrack(track_02, 0)) mka.mux(USBD.a_src) print('\n\n\nAudio cutting') eztrim(USBD.src_clip, (USBD.frame_start, USBD.frame_end), USBD.a_src, mkvextract_path='mkvextract') print('\n\n\nAudio encoding') for i in range(1, len(mka.tracks) + 1): qaac_args = ['qaac64', USBD.a_src_cut.format(i), '-V', '127', '--no-delay', '-o', USBD.a_enc_cut.format(i)] vdf.subprocess.run(qaac_args, text=True, check=True, encoding='utf-8') print('\nFinal muxing') mkv = MKVFile() mkv.add_track(MKVTrack(JPBD.output, language='jpn', default_track=True)) mkv.add_track(MKVTrack(USBD.a_enc_cut.format(2), language='jpn', default_track=True)) mkv.add_track(MKVTrack(USBD.a_enc_cut.format(1), language='eng', default_track=False)) mkv.mux(JPBD.output_final)
def add_subtitle(self, set_default=True): """ Muxes the subtitle in the MKV file and sets it as default if the flag is set appropriately (default True) Parameters ---------- set_default : bool wether to set the muxed subtitle as default subtitle track. Default is `True` """ stats = self._get_stats() subs = self.download_subtitles() movies = list() for idx, _ in enumerate(stats): movies.append({**stats[idx], **subs[idx]}) for movie in movies: if not movie["has_lang"]: sub_track = MKVTrack(movie["sub"]) sub_track.language = self.os_language sub_track.default_track = True if set_default else False mkv_file = MKVFile(movie["file_path"].absolute()) mkv_file.add_track(sub_track) # TODO Handle output folder or file replace config mkv_file.mux(movie["file_path"].stem + "_w_sub.mkv") return True
def do_encode(filtered): """Compression with x264""" print('\n\n\nVideo encoding') vdf.encode(filtered, X264, OUTPUT, True, **X264_ARGS, frames=filtered.num_frames) print('\n\n\nAudio extracting') mka = MKVFile() mka.add_track(MKVTrack(VIDEO_FILES[1], 1)) mka.mux(AUDIO_SRC) print('\n\n\nAudio cutting') eztrim(CLIPS_SRC[1], (0, 1), AUDIO_SRC, outfile=NAME + '_a', ffmpeg_path='') eztrim(CLIPS_SRC[1], (0, 0), AUDIO_SRC, outfile=NAME + '_b', ffmpeg_path='') print('\nFinal muxing') mkv_args = [ 'mkvmerge', '-o', NAME + '.mkv', '--language', '0:jpn', OUTPUT, '--language', '0:jpn', NAME + '_a' + '.mka', '+', NAME + '_b' + '.mka' ] vdf.subprocess.run(mkv_args, text=True, check=True, encoding='utf-8')
class MkvVideoFile(VideoFile): def __init__(self, path: Path, mkvtoolnix_path: Path = None): self.path = path self.folder = path.parent self.mkv_file = MKVFile(path.__str__()) self.logger = logging.getLogger(__name__) if platform.system() == 'Windows': if not mkvtoolnix_path: mkvtoolnix_path = MKVTOOLNIX_WINDOWS_DEFAULT_INSTALL_PATH os.environ['PATH'] += os.pathsep + mkvtoolnix_path self.mkvtoolnix_path = mkvtoolnix_path def get_subtitles_track(self, language): self.logger.debug('Looking for subtitles track for language: %s.', language) if not isinstance(language, tuple): language = language, track: MKVTrack for track in self.mkv_file.tracks: if track.track_type == 'subtitles' and track.language in language: self.logger.info('Found subtitles track for language: %s.', track.language) return track raise Exception( 'Could not find subtitles track for: {}.'.format(language)) def get_subtitles_text(self, language): track = self.get_subtitles_track(language) self.logger.debug('Extracting subtitles.') # TODO until pymkv supports subtitles extraction: subtitles_file_path = self.folder.joinpath('subtitles.txt') subprocess.check_output('mkvextract tracks "{}" {}:{}'.format( self.path.name, track.track_id, subtitles_file_path.name), cwd=self.folder.__str__()) with subtitles_file_path.open('r', encoding='utf-8') as subtitles_file: subtitles_text = subtitles_file.read() os.remove(subtitles_file_path.__str__()) self.logger.debug('Successfully extracted subtitles.') return subtitles_text def add_subtitles(self, subtitles_text: str, language): self.logger.debug('Adding subtitles.') track = self.get_subtitles_track(language) fixed_subtitles_path = self.folder.joinpath('subtitles-fixed.txt') with fixed_subtitles_path.open( 'w', encoding='utf-8') as fixed_subtitles_file: fixed_subtitles_file.write(subtitles_text) fixed_track = MKVTrack(fixed_subtitles_path.__str__()) fixed_track.track_name = track.track_name + '-fixed' fixed_track.language = track.language self.mkv_file.add_track(fixed_track) output_name = Path(self.path.stem + '-fixed').with_suffix( self.path.suffix) output_path = self.path.with_name(output_name) self.mkv_file.mux(output_path.__str__()) os.remove(fixed_subtitles_file.__str__()) self.logger.debug('Successfully added subtitles.')
def generate_file_from_tracks(track_list: MKVtrack, output_dir: str, output_name: str): mkv = MKVfile() for track in track_list: mkv.add_track(track) if output_name[-4:] != ".mkv": output_name = output_name + ".mkv" mkv.mux(output_dir + output_name)
def pack(self, path): mkv = MKVFile() mkv.add_track(MKVTrack(path + self.file_name, track_id=0)) mkv.add_track(MKVTrack(path + self.file_name, track_id=1)) for subtitle in self.subtitles: mkv.add_track(subtitle.to_mkv_track(path)) output = path + self.file_name_mkv logger.info("inicia el empaquetado a '{}'".format(self.file_name)) mkv.mux(output, silent=False) return output
def process_file(file: dict, temp_folder: str): logging.info(f"Processing file {file['input_file_path']}...") if not file.get('subtitle_file_path'): logging.info("Subtitle not found!") if file['input_file_path'] != file['output_file_path']: logging.info("Moving file...") check_and_create_directory(file['output_file_path']) shutil.move(file['input_file_path'], file['output_file_path']) else: logging.info("Subtitle found!") if temp_folder: if not os.path.exists(temp_folder): logging.info( f'Temp dir does not exists. Creating {temp_folder}...') os.mkdir(temp_folder) file['temp_file_path'] = f"{temp_folder}\\{file['input_filename']}" logging.info( f"Copying file from {file['input_file_path']} to {file['temp_file_path']}..." ) shutil.copyfile(file['input_file_path'], file['temp_file_path']) file[ 'temp_output_file_path'] = f"{file['temp_file_path'][:-4]}_output{file['temp_file_path'][-4:]}" mkv_input = file.get('temp_file_path') mkv_output = file.get('temp_output_file_path') if not mkv_input: mkv_input = file.get('input_file_path') if not mkv_output: mkv_output = file.get('output_file_path') if mkv_input == mkv_output: mkv_output = f"{mkv_input[:-4]}_output{mkv_input[-4:]}" mkv = MKVFile(mkv_input) if not check_subtitles(mkv): logging.info("Adding subtitle...") mkv.add_track(file['subtitle_file_path']) mkv.title = file['episode_name'] mkv.tracks[-1].language = 'por' mkv.mux(mkv_output) check_and_create_directory(file['output_file_path']) logging.info( f'Moving {mkv_output} to {file["output_file_path"]}...') shutil.move(mkv_output, file['output_file_path']) logging.info(f"Removing {file['subtitle_file_path']}...") os.remove(file['subtitle_file_path']) if file['input_file_path'] != file['output_file_path']: logging.info(f"Removing {file['input_file_path']}...") os.remove(file['input_file_path']) else: logging.info("Subtitle already added. Skipping...") if file.get('temp_file_path'): logging.info(f"Removing temp file {mkv_input}...") os.remove(mkv_input)
def create_sample_videos(filename, time, tmp_dir): print('Creating sample videos...') mkv = MKVFile(filename) ts_1 = (time - 10, time + 20) ts_2 = (time * 2 - 10, time * 2 + 20) try: mkv.split_timestamp_parts([ts_1, ts_2]) except TypeError: sys.exit('Invalid timestamps! Exiting.') out = os.path.join(tmp_dir, 'sample.mkv') mkv.mux(out) clear()
def mux_movie(movie_file, cover_file): """Generate MKV file with added movie poster Args: movie_file (str): Movie File Path cover_file (str): Image File Path """ sub_path = None full_file_name = movie_file.replace('\\', '/').split('/')[-1] file_name = '.'.join(full_file_name.split('.')[:-1]) file_directory = os.path.dirname(movie_file) output_filename = os.path.join(file_directory, file_name + '.mkv') temp_file_name = 'temp_' + file_name temp_file_path = os.path.join(file_directory, temp_file_name + '.mkv') if movie_file.endswith('.mkv'): mkv = MKVFile(movie_file) else: mkv = MKVFile() i = 0 while True: try: mkv.add_track(MKVTrack(movie_file, track_id=i)) i += 1 except: break mkv.title = file_name attachment = MKVAttachment(cover_file, name='cover.jpg') mkv.no_attachments() mkv.add_attachment(attachment) if ROOT_DIR_PATH != file_directory: sub_path = get_subtitle_file(movie_file) if sub_path: mkv.add_track(MKVTrack(sub_path, track_id=0)) mkv.mux(temp_file_path, silent=True) os.chmod(movie_file, stat.S_IWRITE) os.remove(movie_file) os.rename(temp_file_path, output_filename) if sub_path: # Delete SRT file After Mux os.remove(sub_path) # Check if directory has single file, move movie file outside and del dir if ROOT_DIR_PATH != file_directory: if len(os.listdir(file_directory)) == 1: parent_dir = os.path.dirname(file_directory) os.rename(output_filename, os.path.join(parent_dir, file_name + '.mkv')) os.rmdir(file_directory)
def do_encode(clip: vs.VideoNode)-> None: """Compression with x264""" print('\n\n\nVideo encoding') x265_args = [ X265, "--y4m", "--frames", f"{clip.num_frames}", "--sar", "1", "--output-depth", "10", "--colormatrix", "bt709", "--colorprim", "bt709", "--transfer", "bt709", "--range", "limited", "--min-luma", str(16<<2), "--max-luma", str(235<<2), "--fps", f"{clip.fps_num}/{clip.fps_den}", "-o", JPBD.output, "-", "--frame-threads", "16", "--no-sao", "--fades", "--preset", "slower", "--crf", "14.5", "--qcomp", "0.72", "--bframes", "16", "--psy-rd", "2.0", "--psy-rdoq", "1.0", "--deblock", "-1:-1", "--rc-lookahead", "96", "--min-keyint", "23", "--keyint", "360", "--aq-mode", "3", "--aq-strength", "1.0" ] print("Encoder command: ", " ".join(x265_args), "\n") process = subprocess.Popen(x265_args, stdin=subprocess.PIPE) clip.output(process.stdin, y4m=True, progress_update=lambda value, endvalue: print(f"\rVapourSynth: {value}/{endvalue} ~ {100 * value // endvalue}% || Encoder: ", end="")) process.communicate() print('\n\n\nAudio extraction') mka = MKVFile() mka.add_track(MKVTrack(JPBD.src, 1)) mka.mux(JPBD.a_src) print('\n\n\nAudio cutting') eztrim(JPBD.src_clip, (JPBD.frame_start, JPBD.frame_end), JPBD.a_src, mkvextract_path='mkvextract') print('\n\n\nAudio encoding') qaac_args = ['qaac64', JPBD.a_src_cut.format(1), '-V', '127', '--no-delay', '-o', JPBD.a_enc_cut.format(1)] subprocess.run(qaac_args, text=True, check=True, encoding='utf-8') print('\nFinal muxing') mkv = MKVFile() mkv.add_track(MKVTrack(JPBD.output, language='jpn', default_track=True)) mkv.add_track(MKVTrack(JPBD.a_enc_cut.format(1), language='jpn', default_track=True)) mkv.chapters(JPBD.chapter, 'jpn') mkv.mux(JPBD.output_final)
def main(): logger = logging.getLogger(__name__) SubRipTime.to_timestamp = to_timestamp parser = argparse.ArgumentParser( prog='mkvsubmerge', description='Split MKV file according to timestamp pairs ' 'specified by SRT subtitle file and then merge ' 'into a new video file.') parser.add_argument('mkv', help='MKV file') parser.add_argument('-o', dest='out', help='output MKV file') parser.add_argument('--srt', help='SRT file') parser.add_argument('--srt-encoding', help='SRT file encoding') parser.add_argument('--start-offset', type=int, default=0, help='offset to apply to every start timestamp') parser.add_argument('--end-offset', type=int, default=0, help='offset to apply to every end timestamp') args = parser.parse_args() mkv_path = args.mkv output_path = args.out or '{}.submerge.mkv'.format( path.splitext(mkv_path)[0]) srt_path = args.srt or '{}.srt'.format(path.splitext(mkv_path)[0]) srt_encoding = args.srt_encoding start_offset = args.start_offset end_offset = args.end_offset # Ensure both files exist if not path.exists(mkv_path): logger.error('{} does not exist.'.format(mkv_path)) exit(1) if not path.exists(srt_path): logger.error('{} does not exist.'.format(srt_path)) exit(1) # Read srt file subs = pysrt.open(srt_path, encoding=srt_encoding) subs.clean_indexes() # Sort first to ensure order # Form timestamps timestamps = [] # In even number for sub_item in subs: # Address the key frame problem by introducing offset parameter. # See https://mkvtoolnix.download/doc/mkvmerge.html#mkvmerge.description start_timestamp = (sub_item.start + start_offset).to_timestamp() end_timestamp = (sub_item.end + end_offset).to_timestamp() if len(timestamps) == 0: timestamps.append(start_timestamp) # timestamps.append(0) timestamps.append(end_timestamp) else: last_timestamp = timestamps[-1] if end_timestamp > last_timestamp: # Otherwise the clip is contained by the previous one if start_timestamp > last_timestamp: # Notice that it should be > instead of >= timestamps.append(start_timestamp) timestamps.append(end_timestamp) else: # Replace last timestamp with `end_timestamp` timestamps[-1] = end_timestamp logger.info('{} timestamp pair(s) in total.'.format(len(timestamps) / 2)) # Generate new files mkv = MKVFile(mkv_path) mkv.split_timestamp_parts([timestamps]) mkv.mux(output_path)
import os import glob from pymkv import MKVFile v_path = r'\\Penfever2020\Public\Movie Storage\$.avi' xml_files = glob.glob(r'\\Penfever2020\Public\mtch\*.xml') for xml in xml_files: v_title = xml[27:len(xml) - 4] path_temp = glob.glob(v_path.replace('$', v_title)) dest_temp = v_path.replace('$.avi', v_title + ".mkv") for line in path_temp: if v_title in line: mkv = MKVFile() mkv.add_track(line) mkv.chapters(xml) mkv.mux(dest_temp) if not os.path.isfile( dest_temp) or not os.path.getsize(dest_temp) > 128_000_000: print("MKVToolnix error: new MKV not saved or may be corrupt.") continue v_path_q = '\\\Penfever2020\Public\Movie Storage\\' + v_title + ".avi" v_path_x = '\\\Penfever2020\Public\mtch\\' + v_title + ".xml" cmd = f"del \"{v_path_q}\"" print(cmd) os.system("" + cmd + "") cmd = f"del \"{v_path_x}\"" print(cmd) os.system("" + cmd + "")