Collection of scripts to make automatic video highlights of varying quality
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

114 linhas
3.3 KiB

  1. #!/bin/python
  2. """jsonclips.py - generate highlights based on JSON
  3. usage: jsonclips.py clips.json
  4. JSON file can specify:
  5. - output filename
  6. - source filepath
  7. - start time
  8. - duration
  9. - transition type [default: luma]
  10. - transition duration [default: 30]
  11. """
  12. DEFAULT_TRANSITION_DURATION = 30 # 30 frames, ie 0.5s at 60FPS
  13. DEFAULT_TRANSITION_TYPE = "luma"
  14. def process_highlights(jsonfile):
  15. """Go through highlights, make clips, join to a video"""
  16. import tempfile
  17. def make_clips(sources=None, outputdir=None):
  18. """Use ffmpeg to create output from processed JSON"""
  19. import subprocess
  20. import os
  21. ffmpeg_common_args = ["ffmpeg", "-loglevel", "quiet", "-hide_banner"]
  22. clipnum = 0
  23. for source in sources:
  24. print("Making {}s clip from {} at {}".format(
  25. source["duration"], source["filepath"], source["time"]))
  26. ffmpeg_file_args = ["-ss", str(source["time"]),
  27. "-i", source["filepath"],
  28. "-t", str(source["duration"]),
  29. "-c", "copy",
  30. os.path.join(outputdir,
  31. "clip{}.mkv".format(clipnum))]
  32. ffmpeg_args = ffmpeg_common_args + ffmpeg_file_args
  33. print("Running ffmpeg with args:\n\n{}".
  34. format(ffmpeg_args))
  35. subprocess.run(ffmpeg_args)
  36. clipnum += 1
  37. def make_output(workingdir=None, outputfile=None, numsources=None):
  38. """Use MLT (melt) to join clips"""
  39. import subprocess
  40. import os
  41. melt_args = ["melt"]
  42. for i in range(numsources):
  43. if i == 0:
  44. melt_args.extend([os.path.join(workingdir, "clip{}.mkv"
  45. .format(i))])
  46. else:
  47. melt_args.extend([
  48. os.path.join(workingdir, "clip{}.mkv".format(i)),
  49. "-mix", str(DEFAULT_TRANSITION_DURATION),
  50. "-mixer", str(DEFAULT_TRANSITION_TYPE)])
  51. melt_args.extend(["-consumer", "avformat:{}".format(outputfile),
  52. "crf=20"])
  53. print("Running melt with args:\n\n{}".format(melt_args))
  54. subprocess.run(melt_args)
  55. def parse_json(jsonfile=None):
  56. """Parse global / per--clip options from jsonfile
  57. Requires:
  58. - outputfile
  59. - list of sources
  60. """
  61. import json
  62. import sys
  63. if jsonfile:
  64. with open(jsonfile, "r") as fh:
  65. json_in = json.load(fh)
  66. if "outputfile" not in json_in:
  67. print("Please specify an outputfile to write to")
  68. sys.exit(1)
  69. if "sources" not in json_in:
  70. print("Please specify some sources to process")
  71. sys.exit(1)
  72. return json_in
  73. # Start
  74. if jsonfile:
  75. json_in = parse_json(jsonfile)
  76. # in temporary dir
  77. with tempfile.TemporaryDirectory() as tmpdir:
  78. # make clips
  79. make_clips(sources=json_in["sources"], outputdir=tmpdir)
  80. # join clips using melt
  81. make_output(workingdir=tmpdir, outputfile=json_in["outputfile"],
  82. numsources=len(json_in["sources"]))
  83. if __name__ == "__main__":
  84. import sys
  85. process_highlights(sys.argv[1])