Advertisement
XenoTheStrange

FFMPEG Convert Videos of format [w x y] to format [z] maintaining folder structure (refactor, PS3)

May 13th, 2024 (edited)
620
0
Never
2
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.88 KB | None | 0 0
  1. #!/usr/bin/python3
  2. import argparse
  3. import os
  4. import logging
  5. import subprocess
  6.  
  7. logging.basicConfig(level=logging.DEBUG)
  8. args = ""
  9.  
  10. #HEY YOU! This was meant to convert primarily from mkv to mp4 to be played back on a jailbroken Playstation 3.
  11. #You can edit the `command` variable in the `ffmpeg_convert_standard` function below to remove the junk if you know what you're doing.
  12.  
  13. def parse_arguments():
  14.     filename = __file__.split("/")[-1]
  15.     usage = f"""{filename} -i input_dir -ie [input extensions] -oe output_ext -o output_dir\n   ex: {filename} -i ./input -ie mkv ogg avi -oe mp4 -o ./output"""
  16.     parser = argparse.ArgumentParser(description="Convert media files from one type to another while maintaining the directory structure", usage=usage)
  17.     parser.add_argument("-i", "--in_dir", metavar="dir", default="", type=str, help="Directory containing media files", required=True)
  18.     parser.add_argument("-ie", "--in_exts", metavar="ext", nargs="+", type=str, help="Input filename extensions", required=True)
  19.     parser.add_argument("-oe", "--out_ext", metavar="ext", type=str, help="Output filename extension", required=True)
  20.     parser.add_argument("-o", "--out_dir", metavar="dir", type=str, help="Directory in which to place the converted media files", required=True)
  21.     parser.add_argument("-d", "--debug", action="store_true", help="Enable debug logging")
  22.     parser.add_argument("-ns", "--no_sanatize", action="store_true", help="Do not remove symbols from the output file path")
  23.     parser.add_argument("-f", "--overwrite", action="store_true", help="Make ffmpeg overwrite video files which already exist")
  24.     args = parser.parse_args()
  25.     #Need to make sure that the paths end in a slash for the sake of consistancy
  26.     args.in_dir = add_slash(args.in_dir)
  27.     args.out_dir = add_slash(args.out_dir)
  28.     return args
  29.  
  30. def overwrite():
  31.     global args
  32.     if args.overwrite:
  33.         return "-y"
  34.     else:
  35.         return "-n"
  36.  
  37. def is_input_file(filename):
  38.     global args
  39.     ext = filename.split(".")[-1]
  40.     if ext in args.in_exts:
  41.         return True
  42.     else:
  43.         return False
  44.  
  45. def add_slash(path):
  46.     if not path[-1] == "/":
  47.         path += "/"
  48.     return path
  49.  
  50. """Iterate through all folders in a path and attempt to create them so the output folder structure is correct"""
  51. def ensure_path(path):
  52.     path = add_slash(path)
  53.     arr = path.split("/")
  54.     for i in range(len(arr)):
  55.         try:
  56.             tmp = "/".join(arr[0:i])
  57.             tmp = add_slash(tmp)
  58.             os.mkdir(tmp)
  59.         except Exception as e:
  60.             if args.debug:
  61.                 logging.warn(f"[WARN] ensure_path: {e}")
  62.             continue
  63.  
  64. def name_sanitize(string):
  65.     if args.no_sanatize: return string
  66.     disallow = ["\"","!","?"]
  67.     out = string
  68.     for symbol in disallow:
  69.         out = out.replace(symbol, "_")
  70.     return out
  71.  
  72. def make_paths(path, fname):
  73.     global args
  74.     base_path = add_slash(path).replace(args.in_dir, args.out_dir)
  75.     filename = "".join(fname.split(".")[0:-1])
  76.     ext = args.out_ext
  77.  
  78.     in_path = f"{add_slash(path)}{fname}"
  79.     out_path = name_sanitize(f"""{base_path}{filename}.{ext}""")
  80.     return (in_path, out_path)
  81.  
  82. def get_total_input_files(filetree):
  83.     total = 0
  84.     for entry in filetree:
  85.         for name in entry[2]:
  86.             if is_input_file(name):
  87.                 total += 1
  88.     return total
  89.  
  90. def ffmpeg_convert_standard(in_path, out_path):
  91.     global args
  92.     if not os.path.exists(in_path):
  93.         return f"[ERROR]: Path does not exist: {in_path}"
  94.     ensure_path("/".join(out_path.split("/")[0:-1])) #strip the filename from the path and make output folder structure
  95.     command = f"""ffmpeg -hide_banner -nostats {overwrite()} -i "{in_path}" -c:v libx264 -profile:v high -vf format=yuv420p -bsf:v h264_metadata=video_full_range_flag=0 -c:a aac -ac 2 -dn -map_metadata:c -1 -map_chapters:c -1 "{out_path}" """
  96.     proc = subprocess.run(command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
  97.     stdout = proc.stderr.decode("utf-8")
  98.     stderr = proc.stderr.decode("utf-8")
  99.     output = stdout if stderr=="" else stderr
  100.     if args.debug:
  101.         logging.info(output)
  102.     return
  103.  
  104. """When called from the command line it'll use the arguments to convert some videos"""
  105. def main():
  106.     global args
  107.     args = parse_arguments()
  108.     filetree = sorted(list(os.walk(args.in_dir)))
  109.     current = 0
  110.     total = get_total_input_files(filetree)
  111.     #folder will be a tuple: (this_directory, [folders], [files])
  112.     for thisdir, folders, files in filetree:
  113.         for fname in files:
  114.             if not is_input_file(fname):
  115.                 continue
  116.             current += 1
  117.             in_path, out_path = make_paths(thisdir, fname)
  118.             logging.info(f"[{current}/{total}] Processing file: {in_path}")
  119.             ffmpeg_convert_standard(in_path, out_path)
  120.  
  121. if __name__ == "__main__":
  122.     main()
  123.  
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement