modify ffmpeg commands
This commit is contained in:
@@ -2,7 +2,7 @@ import argparse
|
|||||||
|
|
||||||
from tsmark.video_annotator import Marker
|
from tsmark.video_annotator import Marker
|
||||||
|
|
||||||
VERSION = "0.5.1"
|
VERSION = "0.6.0"
|
||||||
|
|
||||||
|
|
||||||
def get_options():
|
def get_options():
|
||||||
@@ -42,6 +42,21 @@ def get_options():
|
|||||||
type=str,
|
type=str,
|
||||||
help="predefined crop. Syntax: 'w:h:x:y' example: 1280:720:30:20",
|
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("--version", action="version", version=VERSION)
|
||||||
parser.add_argument(action="store", dest="video")
|
parser.add_argument(action="store", dest="video")
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import time
|
|||||||
|
|
||||||
import cv2
|
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:
|
class Marker:
|
||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
@@ -314,8 +321,9 @@ class Marker:
|
|||||||
if colon_count == 2:
|
if colon_count == 2:
|
||||||
hours, mins, secstr = timestr.split(":", 2)
|
hours, mins, secstr = timestr.split(":", 2)
|
||||||
sec = float(secstr)
|
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 ValueError("Cannot parse time definition {}".format(timestr))
|
||||||
|
raise TypeError("Cannot parse time definition {}".format(timestr))
|
||||||
|
|
||||||
def parse_timestamps(self):
|
def parse_timestamps(self):
|
||||||
self.stamps = []
|
self.stamps = []
|
||||||
@@ -326,7 +334,7 @@ class Marker:
|
|||||||
# if row has 3 cols, pick the frame number directly
|
# if row has 3 cols, pick the frame number directly
|
||||||
splitted = row.split(",")
|
splitted = row.split(",")
|
||||||
if len(splitted) == 3:
|
if len(splitted) == 3:
|
||||||
self.stamps.append(int(splitted[2]))
|
self.stamps.append(int(splitted[2], 10))
|
||||||
if len(splitted) < 3:
|
if len(splitted) < 3:
|
||||||
self.opts.timestamps.append(splitted[0])
|
self.opts.timestamps.append(splitted[0])
|
||||||
else:
|
else:
|
||||||
@@ -350,6 +358,7 @@ class Marker:
|
|||||||
if self.crop[2] is None:
|
if self.crop[2] is None:
|
||||||
cropstr = ""
|
cropstr = ""
|
||||||
else:
|
else:
|
||||||
|
self.opts.ffmpeg_copy = False
|
||||||
x, y = [
|
x, y = [
|
||||||
int(self.video_res_original[0] * self.crop[0][0] / self.video_res[0]),
|
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]),
|
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} "
|
cropstr = f"-filter:v crop={w}:{h}:{x}:{y} "
|
||||||
self.stamps.sort()
|
self.stamps.sort()
|
||||||
print("# Timestamps:")
|
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):
|
for i, ts in enumerate(self.stamps):
|
||||||
print("# {}: {} / {}".format(i + 1, self.format_time(ts), ts))
|
print("# {}: {} / {}".format(i + 1, self.format_time(ts), ts))
|
||||||
if len(self.stamps) == 0:
|
if len(self.stamps) == 0:
|
||||||
@@ -375,6 +388,8 @@ class Marker:
|
|||||||
padlen = len(str(self.frames))
|
padlen = len(str(self.frames))
|
||||||
src_name = self.opts.video.replace('"', '\\"')
|
src_name = self.opts.video.replace('"', '\\"')
|
||||||
tgt_name = os.path.splitext(self.opts.video)[0].replace('"', '\\"')
|
tgt_name = os.path.splitext(self.opts.video)[0].replace('"', '\\"')
|
||||||
|
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):
|
for i in range(1, len(self.stamps), 2):
|
||||||
from_ts = self.stamps[i - 1]
|
from_ts = self.stamps[i - 1]
|
||||||
to_ts = self.stamps[i]
|
to_ts = self.stamps[i]
|
||||||
@@ -382,8 +397,9 @@ class Marker:
|
|||||||
to_ft = self.format_time(to_ts)
|
to_ft = self.format_time(to_ts)
|
||||||
from_str = str(from_ts).zfill(padlen)
|
from_str = str(from_ts).zfill(padlen)
|
||||||
to_str = str(to_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"')
|
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):
|
def save_timestamps(self):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user