|
@@ -24,15 +24,10 @@ min_clip_length = 1.0
|
|
|
|
|
|
|
|
|
import audioop
|
|
|
-import datetime
|
|
|
-import os
|
|
|
-import shutil
|
|
|
import subprocess
|
|
|
import sys
|
|
|
-import tempfile
|
|
|
-from multiprocessing.pool import ThreadPool
|
|
|
|
|
|
-# TODO: kill ffmpeg processes on Ctrl+C
|
|
|
+# TODO: optimize
|
|
|
|
|
|
|
|
|
def get_audio_streams(filename):
|
|
@@ -56,7 +51,7 @@ def get_audio_streams(filename):
|
|
|
return list(filter(lambda s: s["codec_type"] == "audio", streams))
|
|
|
|
|
|
|
|
|
-def get_clips(stream, sample_rate):
|
|
|
+def print_skips(stream, sample_rate):
|
|
|
clips = []
|
|
|
clip_index = 0
|
|
|
loud_start = -1
|
|
@@ -80,46 +75,28 @@ def get_clips(stream, sample_rate):
|
|
|
|
|
|
clips = list(filter(lambda v: (v[1] - v[0]) > min_clip_length * 100, clips))
|
|
|
|
|
|
- return clips
|
|
|
-
|
|
|
-
|
|
|
-def index_to_time(index):
|
|
|
- millis = index * 10 % 1000
|
|
|
- seconds = index // 100
|
|
|
- hours = seconds // (60 * 60)
|
|
|
- seconds %= 60 * 60
|
|
|
- minutes = seconds // 60
|
|
|
- seconds %= 60
|
|
|
- return "%02i:%02i:%02i.%03i" % (hours, minutes, seconds, millis)
|
|
|
-
|
|
|
-
|
|
|
-def encode(tmpdir, i, clip):
|
|
|
- path = os.path.join(tmpdir, f"part{i}.mkv")
|
|
|
- subprocess.call(
|
|
|
- [
|
|
|
- "ffmpeg",
|
|
|
- "-i",
|
|
|
- filename,
|
|
|
- "-ss",
|
|
|
- index_to_time(clip[0]),
|
|
|
- "-to",
|
|
|
- index_to_time(clip[1]),
|
|
|
- "-c:v",
|
|
|
- "copy",
|
|
|
- path,
|
|
|
- ],
|
|
|
- stdout=subprocess.DEVNULL,
|
|
|
- stderr=subprocess.DEVNULL,
|
|
|
- )
|
|
|
+ # Turn clips into skips
|
|
|
+ skips = []
|
|
|
+ last_skip = 0
|
|
|
+ for clip in clips:
|
|
|
+ if last_skip == clip[0]:
|
|
|
+ last_skip = clip[1]
|
|
|
+ else:
|
|
|
+ skips.append((last_skip, clip[0]))
|
|
|
+ last_skip = clip[1]
|
|
|
+
|
|
|
+ # Fix time format (1 index = 10ms)
|
|
|
+ index_to_time = lambda index: index / 100
|
|
|
+ skips = [(index_to_time(skip[0]), index_to_time(skip[1])) for skip in skips]
|
|
|
+
|
|
|
+ skips = ["{" + f"{v[0]},{v[1]}" + "}" for v in skips]
|
|
|
+ print("return {" + ",".join(skips) + "}")
|
|
|
|
|
|
|
|
|
for filename in sys.argv[1:]:
|
|
|
for stream in get_audio_streams(filename):
|
|
|
index = int(stream["index"])
|
|
|
sample_rate = int(stream["sample_rate"])
|
|
|
- nb_samples = int(stream["duration_ts"])
|
|
|
- duration_seconds = nb_samples / sample_rate
|
|
|
- print(f"Analyzing {duration_seconds:.2f} seconds of audio...")
|
|
|
|
|
|
orig_audio = subprocess.Popen(
|
|
|
[
|
|
@@ -142,52 +119,7 @@ for filename in sys.argv[1:]:
|
|
|
stderr=subprocess.DEVNULL,
|
|
|
)
|
|
|
|
|
|
- clips = get_clips(orig_audio.stdout, sample_rate)
|
|
|
- tmpdir = tempfile.mkdtemp()
|
|
|
- clipfiles = [os.path.join(tmpdir, f"part{i}.mkv") for i, _ in enumerate(clips)]
|
|
|
-
|
|
|
- max = len(clips)
|
|
|
- progress = -1
|
|
|
-
|
|
|
- def update_progress(*args):
|
|
|
- global progress
|
|
|
- progress += 1
|
|
|
- bar_size = 60
|
|
|
- n = int(bar_size * progress / max)
|
|
|
- pounds = "#" * n
|
|
|
- dots = "." * (bar_size - n)
|
|
|
- sys.stdout.write(f"Cutting: [{pounds}{dots}] {progress}/{max}\r")
|
|
|
- sys.stdout.flush()
|
|
|
-
|
|
|
- update_progress()
|
|
|
- pool = ThreadPool()
|
|
|
- for i, clip in enumerate(clips):
|
|
|
- res = pool.apply_async(encode, (tmpdir, i, clip), callback=update_progress)
|
|
|
- pool.close()
|
|
|
-
|
|
|
- pool.join()
|
|
|
- sys.stdout.write("\n")
|
|
|
- sys.stdout.flush()
|
|
|
-
|
|
|
- cliplist = os.path.join(tmpdir, "list.txt")
|
|
|
- with open(cliplist, "w") as filelist:
|
|
|
- filelist.write("ffconcat version 1.0\n\n")
|
|
|
- for fn in clipfiles:
|
|
|
- filelist.write(f"file '{fn}'\n")
|
|
|
-
|
|
|
- subprocess.call(
|
|
|
- [
|
|
|
- "ffmpeg",
|
|
|
- "-f",
|
|
|
- "concat",
|
|
|
- "-safe",
|
|
|
- "0",
|
|
|
- "-i",
|
|
|
- cliplist,
|
|
|
- "-c",
|
|
|
- "copy",
|
|
|
- filename[:-4] + "_cutout.mkv",
|
|
|
- ]
|
|
|
- )
|
|
|
+ print_skips(orig_audio.stdout, sample_rate)
|
|
|
|
|
|
- shutil.rmtree(tmpdir)
|
|
|
+ # We're only using the first audio stream
|
|
|
+ break
|