|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- #!/bin/python
- """jsonclips.py - generate highlights based on JSON
-
- usage: jsonclips.py clips.json
-
- JSON file can specify:
- - output filename
- - source filepath
- - start time
- - duration
- - transition type [default: luma]
- - transition duration [default: 30]
- """
-
- DEFAULT_TRANSITION_DURATION = 30 # 30 frames, ie 0.5s at 60FPS
- DEFAULT_TRANSITION_TYPE = "luma"
-
-
- def process_highlights(jsonfile):
- """Go through highlights, make clips, join to a video"""
- import tempfile
-
- def make_clips(sources=None, outputdir=None):
- """Use ffmpeg to create output from processed JSON"""
- import subprocess
- import os
-
- ffmpeg_common_args = ["ffmpeg", "-loglevel", "quiet", "-hide_banner"]
- clipnum = 0
-
- for source in sources:
- print("Making {}s clip from {} at {}".format(
- source["duration"], source["filepath"], source["time"]))
-
- ffmpeg_file_args = ["-ss", str(source["time"]),
- "-i", source["filepath"],
- "-t", str(source["duration"]),
- "-c", "copy",
- os.path.join(outputdir,
- "clip{}.mkv".format(clipnum))]
-
- ffmpeg_args = ffmpeg_common_args + ffmpeg_file_args
- print("Running ffmpeg with args:\n\n{}".
- format(ffmpeg_args))
- subprocess.run(ffmpeg_args)
-
- clipnum += 1
-
- def make_output(workingdir=None, outputfile=None, numsources=None):
- """Use MLT (melt) to join clips"""
- import subprocess
- import os
-
- melt_args = ["melt"]
-
- for i in range(numsources):
- if i == 0:
- melt_args.extend([os.path.join(workingdir, "clip{}.mkv"
- .format(i))])
- else:
- melt_args.extend([
- os.path.join(workingdir, "clip{}.mkv".format(i)),
- "-mix", str(DEFAULT_TRANSITION_DURATION),
- "-mixer", str(DEFAULT_TRANSITION_TYPE)])
-
- melt_args.extend(["-consumer", "avformat:{}".format(outputfile),
- "crf=20"])
-
- print("Running melt with args:\n\n{}".format(melt_args))
- subprocess.run(melt_args)
-
- def parse_json(jsonfile=None):
- """Parse global / per--clip options from jsonfile
-
- Requires:
- - outputfile
- - list of sources
- """
- import json
- import sys
-
- if jsonfile:
- with open(jsonfile, "r") as fh:
- json_in = json.load(fh)
-
- if "outputfile" not in json_in:
- print("Please specify an outputfile to write to")
- sys.exit(1)
-
- if "sources" not in json_in:
- print("Please specify some sources to process")
- sys.exit(1)
-
- return json_in
-
- # Start
-
- if jsonfile:
- json_in = parse_json(jsonfile)
-
- # in temporary dir
- with tempfile.TemporaryDirectory() as tmpdir:
- # make clips
- make_clips(sources=json_in["sources"], outputdir=tmpdir)
- # join clips using melt
- make_output(workingdir=tmpdir, outputfile=json_in["outputfile"],
- numsources=len(json_in["sources"]))
-
-
- if __name__ == "__main__":
- import sys
-
- process_highlights(sys.argv[1])
|