add --chapters
This commit is contained in:
parent
9b2477a39b
commit
37b4d2d34d
2 changed files with 46 additions and 3 deletions
|
@ -35,6 +35,7 @@ command.sub_vp9 = Command("-codec:v", "libvpx-vp9", "-crf", "QUALITY", "-b:v", "
|
|||
command.sub_av1 = Command("-strict", "experimental", "-codec:v", "libaom-av1", "-crf", "QUALITY", "-b:v", "0", "VFILTER")
|
||||
command.sub_normalize = Command("-filter:a", "LOUDNORM_INCANTATION", "-ar", "48k")
|
||||
command.sub_vfilter = Command("-filter:v", "ARGS")
|
||||
command.merge_chapters = Command("mkvmerge", "--chapters", "CHAPTERS_FILE", "-o", "OUTFILE", "INFILE")
|
||||
command.force_yuv420p = Command("-pix_fmt", "yuv420p")
|
||||
command.sub_copy_audio = Command("-codec:a", "copy")
|
||||
command.sub_copy_video = Command("-codec:v", "copy")
|
||||
|
@ -52,6 +53,7 @@ if __name__ == "__main__":
|
|||
main.add_option("normalize", "Normalize the audio track without clipping. May use dynamic range compression.", bool, [True], abbr="n")
|
||||
main.add_option("ffmpeg-vfilter", 'Raw ffmpeg -filter:v options, e.g. "<M>scale=1280:trunc(ow/a/2)*2,transpose=dir=1<.>"', str, abbr="F", count=1)
|
||||
main.add_option("ffmpeg-map", "Raw ffmpeg <c>-map<.> options, e.g. <W>--<g>map<.> <M>0:1<.> <W>--<g>map<.> <M>0:2<.>. This is a drop-in fix until we get proper stream selection.", str, abbr="M", overwrite=False, count=1)
|
||||
main.add_option("chapters", "Path to a Matroska chapters file. See [<W>Chapters<.>].", str, count=1)
|
||||
main.add_option("cut", "Start timestamp and the duration of the portion to use. Uses native ffmpeg <c>-ss<.> and <c>-to<.> format, so it's either seconds from start or <M>[<HH>:]<MM>:<SS>[.<<m>...]<.>. Example: <W>--<g>cut<.> <M>25 10<.> uses 10 seconds of video starting at 25s, <W>--<g>cut<.> <M>1:10:45 13:9.5<.> uses video from 4245s to 5034.5s.", over.callback.strings, abbr="X", count=2)
|
||||
main.add_option("fps", "Override input framerate.", float, abbr="f", count=1)
|
||||
main.add_option("output", "Force an output filename. Note that this overrides <W>--<g>container<.> as we're relying on ffmpeg's container detection by reading the suffix. Pass an empty string to use the container's default suffix.", str, [""], count=1)
|
||||
|
@ -64,6 +66,7 @@ if __name__ == "__main__":
|
|||
main.add_doc("Description", ["A video converter meant to coerce all video formats into one format with properly normalized audio. It can also be used to extract audio from video files, resizing, or very basic cutting."])
|
||||
main.add_doc("Known good encoder settings", ["<W>vp9<.>: <W>--<g>video<.> <M>vp9<.> <W>--<g>video-quality<.> <M>31<.> <W>--<g>audio<.> <M>opus<.> (this is the default and should provide best overall results)", "<W>x264<.>: <W>--<g>video<.> <M>x264<.> <W>--<g>video-preset<.> <M>slow<.> <W>--<g>video-quality<.> <M>22<.>", "<W>x265<.>: <W>--<g>video<.> <M>x265<.> <W>--<g>video-preset<.> <M>medium<.> <W>--<g>video-quality<.> <M>20<.>"])
|
||||
main.add_doc("Performance", ["Good bitstreams take obscene amounts of CPU time to produce. See /doc/codec-comparison.tsv for a table of various configs encoding a 1080p video.", "AV1 is currently unusable due to the amount of time it takes to produce a single frame."])
|
||||
main.add_doc("Chapters", ["Over-video can add chapters to a MKV file. The definition is taken from a separate file with the following syntax:", "CHAPTER<m>xx<.>=HH:MM:SS.SSS\n CHAPTER<m>xx<.>NAME=chapter's name\n (...)", "(where <m>xx<.> is a counter starting from 01)"])
|
||||
|
||||
main.setup()
|
||||
|
||||
|
@ -107,6 +110,16 @@ if __name__ == "__main__":
|
|||
elif main.cfg.audio == "opus":
|
||||
files.container = "opus"
|
||||
|
||||
if main.cfg.chapters:
|
||||
if main.cfg.container != "mkv":
|
||||
main.print("unable to use <W>--<G>chapters<.> with <W>--<G>container<.> <R>%s<.>" %(main.cfg.container))
|
||||
main.exit(1)
|
||||
|
||||
files.container = "mka"
|
||||
|
||||
if not os.path.exists(main.cfg.chapters):
|
||||
raise FileNotFoundError(main.cfg.chapters)
|
||||
|
||||
main.print("settings", main.print.tl.start, end=":\n")
|
||||
main.print("audio: %s" %(", ".join(audio_words)))
|
||||
main.print("video: %s" %(", ".join(video_words)))
|
||||
|
@ -282,7 +295,7 @@ if __name__ == "__main__":
|
|||
loudnorm_dict = json.loads(output[output.index(b"{"):].decode("ascii"))
|
||||
info.loudnorm = over.types.ndict({k: aux.float_or_string(v) for k, v in loudnorm_dict.items()})
|
||||
else:
|
||||
main.print("<r>unexpected ffmpeg output<.>, dump follows", main.print.tl.fail, suffix=":\n")
|
||||
main.print("<r>unexpected ffmpeg output<.>, dump follows", main.print.tl.fail, end=":\n")
|
||||
print(output.decode("utf-8"))
|
||||
raise RuntimeError
|
||||
|
||||
|
@ -465,6 +478,36 @@ if __name__ == "__main__":
|
|||
main.print("<r>encoding failed<.>, ffmpeg returned <y>%d<.>" %(encode_cmd.returncode), main.print.tl.fail)
|
||||
raise RuntimeError
|
||||
|
||||
# --------------------------------------------------
|
||||
# inject chapters
|
||||
|
||||
if main.cfg.chapters:
|
||||
if main.cfg.dump_commands or main.cfg.armed:
|
||||
files.tmpfile_nochapters = aux.to_Path("nochapter-" + str(files.tmpfile)) # really pathlib?
|
||||
|
||||
command.merge_chapters.reset()
|
||||
command.merge_chapters.CHAPTERS_FILE = main.cfg.chapters
|
||||
command.merge_chapters.OUTFILE = files.tmpfile
|
||||
command.merge_chapters.INFILE = files.tmpfile_nochapters
|
||||
cmd = " ".join(command.merge_chapters.dump(pretty=True))
|
||||
|
||||
if main.cfg.armed:
|
||||
main.print("moving <W>%s<.> -> <W>%s<.>" %(files.tmpfile, files.tmpfile_nochapters), main.print.tl.start)
|
||||
files.tmpfile.rename(files.tmpfile_nochapters)
|
||||
|
||||
main.print("executing <W>%s<.>" %(cmd), main.print.tl.start)
|
||||
command.merge_chapters.run()
|
||||
_ = command.merge_chapters.get_all_output()
|
||||
|
||||
main.print("deleting <W>%s<.>" %(files.tmpfile_nochapters))
|
||||
files.tmpfile_nochapters.unlink()
|
||||
else:
|
||||
main.print("will move <W>%s<.> -> <W>%s<.>" %(files.tmpfile, files.tmpfile_nochapters))
|
||||
main.print("will execute <W>%s<.>" %(cmd))
|
||||
main.print("will delete <W>%s<.>" %(files.tmpfile_nochapters))
|
||||
else:
|
||||
main.print("will add chapters from <W>%s<.>" %(main.cfg.chapters))
|
||||
|
||||
# --------------------------------------------------
|
||||
# shuffle files around
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# encoding: utf-8
|
||||
|
||||
major = 1 # VERSION_MAJOR_IDENTIFIER
|
||||
minor = 114 # VERSION_MINOR_IDENTIFIER
|
||||
# VERSION_LAST_MM 1.114
|
||||
minor = 115 # VERSION_MINOR_IDENTIFIER
|
||||
# VERSION_LAST_MM 1.115
|
||||
patch = 0 # VERSION_PATCH_IDENTIFIER
|
||||
str = ".".join(str(v) for v in (major, minor, patch))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue