From 0932a6190d50c2802bb5942961225898a51b3c6c Mon Sep 17 00:00:00 2001 From: q Date: Thu, 16 Jan 2025 16:45:07 +0200 Subject: [PATCH] modify ffmpeg commands --- tsmark/__init__.py | 17 ++++++++++++++++- tsmark/video_annotator.py | 34 +++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/tsmark/__init__.py b/tsmark/__init__.py index 6cf4115..15464df 100644 --- a/tsmark/__init__.py +++ b/tsmark/__init__.py @@ -2,7 +2,7 @@ import argparse from tsmark.video_annotator import Marker -VERSION = "0.5.1" +VERSION = "0.6.0" def get_options(): @@ -42,6 +42,21 @@ def get_options(): type=str, help="predefined crop. Syntax: 'w:h:x:y' example: 1280:720:30:20", ) + parser.add_argument( + "--ffmpeg-copy", + action="store_true", + default=False, + required=False, + help="Print FFMPEG commands: Copy instead of recompress. If video is cropped, it must be recompressed", + ) + parser.add_argument( + "--ffmpeg-an", + action="store_true", + default=False, + required=False, + help="Print FFMPEG commands: Discard audio track", + ) + parser.add_argument("--version", action="version", version=VERSION) parser.add_argument(action="store", dest="video") return parser.parse_args() diff --git a/tsmark/video_annotator.py b/tsmark/video_annotator.py index 22fbbef..2cd3b79 100755 --- a/tsmark/video_annotator.py +++ b/tsmark/video_annotator.py @@ -4,6 +4,13 @@ import time import cv2 +AUDIO_COMPRESS = "-c:a libmp3lame -ar 44100 -b:a 192k" +AUDIO_COPY = "-c:a copy" +AUDIO_DISCARD = "-an" +VIDEO_COMPRESS = "-c:v mpeg2video -q:v 3 -g 1" +VIDEO_COPY = "-c:v copy" +EXT_COMPRESS = ".mpeg" + class Marker: def __init__(self, opts): @@ -314,8 +321,9 @@ class Marker: if colon_count == 2: hours, mins, secstr = timestr.split(":", 2) sec = float(secstr) - return int(self.fps * (int(hours) * 3600 + int(mins) * 60 + sec), 0) + return int(self.fps * (int(hours, 10) * 3600 + int(mins, 10) * 60 + sec)) raise ValueError("Cannot parse time definition {}".format(timestr)) + raise TypeError("Cannot parse time definition {}".format(timestr)) def parse_timestamps(self): self.stamps = [] @@ -326,7 +334,7 @@ class Marker: # if row has 3 cols, pick the frame number directly splitted = row.split(",") if len(splitted) == 3: - self.stamps.append(int(splitted[2])) + self.stamps.append(int(splitted[2], 10)) if len(splitted) < 3: self.opts.timestamps.append(splitted[0]) else: @@ -350,6 +358,7 @@ class Marker: if self.crop[2] is None: cropstr = "" else: + self.opts.ffmpeg_copy = False x, y = [ int(self.video_res_original[0] * self.crop[0][0] / self.video_res[0]), int(self.video_res_original[1] * self.crop[0][1] / self.video_res[1]), @@ -367,6 +376,10 @@ class Marker: cropstr = f"-filter:v crop={w}:{h}:{x}:{y} " self.stamps.sort() print("# Timestamps:") + audio_str = AUDIO_COPY if self.opts.ffmpeg_copy else AUDIO_COMPRESS + video_str = VIDEO_COPY if self.opts.ffmpeg_copy else VIDEO_COMPRESS + audio_str = AUDIO_DISCARD if self.opts.ffmpeg_an else audio_str + for i, ts in enumerate(self.stamps): print("# {}: {} / {}".format(i + 1, self.format_time(ts), ts)) if len(self.stamps) == 0: @@ -375,15 +388,18 @@ class Marker: padlen = len(str(self.frames)) src_name = self.opts.video.replace('"', '\\"') tgt_name = os.path.splitext(self.opts.video)[0].replace('"', '\\"') - for i in range(1,len(self.stamps),2): - from_ts = self.stamps[i-1] - to_ts = self.stamps[i] + tgt_ext = os.path.splitext(self.opts.video)[1] if self.opts.ffmpeg_copy else EXT_COMPRESS + + for i in range(1, len(self.stamps), 2): + from_ts = self.stamps[i - 1] + to_ts = self.stamps[i] from_ft = self.format_time(from_ts) to_ft = self.format_time(to_ts) - from_str=str(from_ts).zfill(padlen) - to_str=str(to_ts).zfill(padlen) - print(f'ffmpeg -i "{src_name}" {cropstr}-c:v mpeg2video -q:v 3 -g 1 -c:a libmp3lame -ar 44100 -b:a 192k -ss {from_ft} -to {to_ft} "{tgt_name}.trim.{from_str}-{to_str}.mpeg"') - + from_str = str(from_ts).zfill(padlen) + to_str = str(to_ts).zfill(padlen) + print( + f'ffmpeg -i "{src_name}" {cropstr}{video_str} {audio_str} -ss {from_ft} -to {to_ft} "{tgt_name}.trim.{from_str}-{to_str}{tgt_ext}"' + ) def save_timestamps(self):