callmedougan

Using Python script to cut long videos into chunks in FFMPEG

Jun 28th, 2021 (edited)
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.22 KB | None | 0 0
  1. FAILED
  2. https://stackoverflow.com/questions/28884159/using-python-script-to-cut-long-videos-into-chunks-in-ffmpeg
  3.  
  4. USE https://c0decracker.medium.com/auto-splitting-video-file-in-equal-chunks-with-ffmpeg-and-python-706ec28e5daa
  5. https://github.com/c0decracker/video-splitter/blob/master/ffmpeg-split.py
  6.  
  7. import csv
  8. import subprocess
  9. import math
  10. import json
  11. import os
  12. import shlex
  13. from optparse import OptionParser
  14.  
  15.  
  16. def split_by_manifest(filename, manifest, vcodec="copy", acodec="copy",
  17. extra="", **kwargs):
  18. """ Split video into segments based on the given manifest file.
  19. Arguments:
  20. filename (str) - Location of the video.
  21. manifest (str) - Location of the manifest file.
  22. vcodec (str) - Controls the video codec for the ffmpeg video
  23. output.
  24. acodec (str) - Controls the audio codec for the ffmpeg video
  25. output.
  26. extra (str) - Extra options for ffmpeg.
  27. """
  28. if not os.path.exists(manifest):
  29. print("File does not exist: %s" % manifest)
  30. raise SystemExit
  31.  
  32. with open(manifest) as manifest_file:
  33. manifest_type = manifest.split(".")[-1]
  34. if manifest_type == "json":
  35. config = json.load(manifest_file)
  36. elif manifest_type == "csv":
  37. config = csv.DictReader(manifest_file)
  38. else:
  39. print("Format not supported. File must be a csv or json file")
  40. raise SystemExit
  41.  
  42. split_cmd = ["ffmpeg", "-i", filename, "-vcodec", vcodec,
  43. "-acodec", acodec, "-y"] + shlex.split(extra)
  44. try:
  45. fileext = filename.split(".")[-1]
  46. except IndexError as e:
  47. raise IndexError("No . in filename. Error: " + str(e))
  48. for video_config in config:
  49. split_str = ""
  50. split_args = []
  51. try:
  52. split_start = video_config["start_time"]
  53. split_length = video_config.get("end_time", None)
  54. if not split_length:
  55. split_length = video_config["length"]
  56. filebase = video_config["rename_to"]
  57. if fileext in filebase:
  58. filebase = ".".join(filebase.split(".")[:-1])
  59.  
  60. split_args += ["-ss", str(split_start), "-t",
  61. str(split_length), filebase + "." + fileext]
  62. print("########################################################")
  63. print("About to run: "+" ".join(split_cmd+split_args))
  64. print("########################################################")
  65. subprocess.check_output(split_cmd+split_args)
  66. except KeyError as e:
  67. print("############# Incorrect format ##############")
  68. if manifest_type == "json":
  69. print("The format of each json array should be:")
  70. print("{start_time: <int>, length: <int>, rename_to: <string>}")
  71. elif manifest_type == "csv":
  72. print("start_time,length,rename_to should be the first line ")
  73. print("in the csv file.")
  74. print("#############################################")
  75. print(e)
  76. raise SystemExit
  77.  
  78. def get_video_length(filename):
  79.  
  80. output = subprocess.check_output(("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", filename)).strip()
  81. video_length = int(float(output))
  82. print("Video length in seconds: "+str(video_length))
  83.  
  84. return video_length
  85.  
  86. def ceildiv(a, b):
  87. return int(math.ceil(a / float(b)))
  88.  
  89. def split_by_seconds(filename, split_length, vcodec="copy", acodec="copy",
  90. extra="", video_length=None, **kwargs):
  91. if split_length and split_length <= 0:
  92. print("Split length can't be 0")
  93. raise SystemExit
  94.  
  95. if not video_length:
  96. video_length = get_video_length(filename)
  97. split_count = ceildiv(video_length, split_length)
  98. if(split_count == 1):
  99. print("Video length is less then the target split length.")
  100. raise SystemExit
  101.  
  102. split_cmd = ["ffmpeg", "-i", filename, "-vcodec", vcodec, "-acodec", acodec] + shlex.split(extra)
  103. try:
  104. filebase = ".".join(filename.split(".")[:-1])
  105. fileext = filename.split(".")[-1]
  106. except IndexError as e:
  107. raise IndexError("No . in filename. Error: " + str(e))
  108. for n in range(0, split_count):
  109. split_args = []
  110. if n == 0:
  111. split_start = 0
  112. else:
  113. split_start = split_length * n
  114.  
  115. split_args += ["-ss", str(split_start), "-t", str(split_length),
  116. filebase + "-" + str(n+1) + "-of-" + \
  117. str(split_count) + "." + fileext]
  118. print("About to run: "+" ".join(split_cmd+split_args))
  119. subprocess.check_output(split_cmd+split_args)
  120.  
  121.  
  122. def main():
  123. parser = OptionParser()
  124.  
  125. parser.add_option("-f", "--file",
  126. dest = "filename",
  127. help = "File to split, for example sample.avi",
  128. type = "string",
  129. action = "store"
  130. )
  131. parser.add_option("-s", "--split-size",
  132. dest = "split_length",
  133. help = "Split or chunk size in seconds, for example 10",
  134. type = "int",
  135. action = "store"
  136. )
  137. parser.add_option("-c", "--split-chunks",
  138. dest = "split_chunks",
  139. help = "Number of chunks to split to",
  140. type = "int",
  141. action = "store"
  142. )
  143. parser.add_option("-S", "--split-filesize",
  144. dest = "split_filesize",
  145. help = "Split or chunk size in bytes (approximate)",
  146. type = "int",
  147. action = "store"
  148. )
  149. parser.add_option("--filesize-factor",
  150. dest = "filesize_factor",
  151. help = "with --split-filesize, use this factor in time to" \
  152. " size heuristics [default: %default]",
  153. type = "float",
  154. action = "store",
  155. default = 0.95
  156. )
  157. parser.add_option("--chunk-strategy",
  158. dest = "chunk_strategy",
  159. help = "with --split-filesize, allocate chunks according to" \
  160. " given strategy (eager or even)",
  161. type = "choice",
  162. action = "store",
  163. choices = ['eager', 'even'],
  164. default = 'eager'
  165. )
  166. parser.add_option("-m", "--manifest",
  167. dest = "manifest",
  168. help = "Split video based on a json manifest file. ",
  169. type = "string",
  170. action = "store"
  171. )
  172. parser.add_option("-v", "--vcodec",
  173. dest = "vcodec",
  174. help = "Video codec to use. ",
  175. type = "string",
  176. default = "copy",
  177. action = "store"
  178. )
  179. parser.add_option("-a", "--acodec",
  180. dest = "acodec",
  181. help = "Audio codec to use. ",
  182. type = "string",
  183. default = "copy",
  184. action = "store"
  185. )
  186. parser.add_option("-e", "--extra",
  187. dest = "extra",
  188. help = "Extra options for ffmpeg, e.g. '-e -threads 8'. ",
  189. type = "string",
  190. default = "",
  191. action = "store"
  192. )
  193. (options, args) = parser.parse_args()
  194.  
  195. def bailout():
  196. parser.print_help()
  197. raise SystemExit
  198.  
  199. if not options.filename:
  200. bailout()
  201.  
  202. if options.manifest:
  203. split_by_manifest(**(options.__dict__))
  204. else:
  205. video_length = None
  206. if not options.split_length:
  207. video_length = get_video_length(options.filename)
  208. file_size = os.stat(options.filename).st_size
  209. split_filesize = None
  210. if options.split_filesize:
  211. split_filesize = int(options.split_filesize * options.filesize_factor)
  212. if split_filesize and options.chunk_strategy == 'even':
  213. options.split_chunks = ceildiv(file_size, split_filesize)
  214. if options.split_chunks:
  215. options.split_length = ceildiv(video_length, options.split_chunks)
  216. if not options.split_length and split_filesize:
  217. options.split_length = int(split_filesize / float(file_size) * video_length)
  218. if not options.split_length:
  219. bailout()
  220. split_by_seconds(video_length=video_length, **(options.__dict__))
  221.  
  222. if __name__ == '__main__':
  223. main()
  224.  
  225.  
  226.  
  227.  
  228.  
Add Comment
Please, Sign In to add comment