Quellcode durchsuchen

Improve minute transitions

- Fix skips lasting to the end of the minute not being registered
- Merge skips that last more than a minute
- Add a margin to account for noises ending as a new minute starts
Clément Wolf vor 1 Jahr
Ursprung
Commit
77bab19afa
3 geänderte Dateien mit 92 neuen und 33 gelöschten Zeilen
  1. 69 2
      cutitout.lua
  2. 22 31
      cutitout_shared/cutitout.py
  3. 1 0
      cutitout_shared/main.lua

+ 69 - 2
cutitout.lua

@@ -15,11 +15,60 @@
 -- along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 
+-- Margin before and after a clip (in seconds)
+local clip_margin = 0.4
+assert(clip_margin >= 0.0)
+
+-- How loud should noise be to be considered a sound?
+local audio_treshold = 0.01
+assert(audio_treshold > 0.0 and audio_treshold <= 1.0)
+
+-- Minimum clip length (in seconds)
+-- Sounds shorter than that will be considered noise and cut.
+local min_clip_length = 0.2
+assert(min_clip_length > 0.0)
+
+-- Minimum silence length to skip (in seconds)
+local min_skip_length = 2.0
+assert(min_skip_length > 2 * clip_margin)
+
+
 local enabled = false
 local minutes = {}
 local skips = {}
 
+
+function fix_boundaries()
+    -- Merge skips across minutes (required for next step)
+    for ia, a in pairs(skips) do
+        for ib, b in pairs(skips) do
+            if ia ~= ib and (b[1] - a[2] < min_clip_length) then
+                table.insert(skips, {a[1], b[2]})
+
+                if ia > ib then
+                    table.remove(skips, ia)
+                    table.remove(skips, ib)
+                else
+                    table.remove(skips, ib)
+                    table.remove(skips, ia)
+                end
+
+                return fix_boundaries()
+            end
+        end
+    end
+
+    -- Add margin when someone stops talking right as the minute rolls over
+    for _, a in pairs(skips) do
+        if a[1] > 0.0 and a[1] % 60.0 == 0.0 then
+            a[1] = a[1] + clip_margin
+        end
+    end
+end
+
 function load_minute(minute)
+    if minutes[minute] == "loading" then return end
+
     local utils = require("mp.utils")
     local scripts_dir = mp.find_config_file("scripts")
     local cutitoutpy = utils.join_path(scripts_dir, "cutitout_shared/cutitout.py")
@@ -31,13 +80,31 @@ function load_minute(minute)
         name = "subprocess",
         capture_stdout = true,
         playback_only = false,
-        args = { "python3", cutitoutpy, video_path, tostring(minute - 1) }
+        args = {
+            "python3", cutitoutpy, video_path, tostring(minute - 1),
+            tostring(clip_margin), tostring(audio_treshold),
+            tostring(min_clip_length), tostring(min_skip_length),
+        }
     }, function(res, val, err)
         new_skips = loadstring(val.stdout)()
 
-        for _, skip in pairs(new_skips) do table.insert(skips, skip) end
+        local seconds_skippable = 0.0
+        for _, skip in pairs(new_skips) do
+            table.insert(skips, skip)
+            seconds_skippable = seconds_skippable + (skip[2] - skip[1])
+        end
+
+        fix_boundaries()
         minutes[minute] = "loaded"
+
         print(tostring(#new_skips) .. " skips loaded for minute " .. tostring(minute - 1))
+        print(tostring(math.floor(seconds_skippable)) .. " seconds skippable in minute " .. tostring(minute - 1))
+
+        -- If majority of the minute is skippable, keep looking for skips
+        -- (so silent videos portions lasting more than 2 minutes get skipped in one go)
+        if seconds_skippable > 30 then
+            load_minute(minute + 1)
+        end
     end)
 end
 

+ 22 - 31
cutitout_shared/cutitout.py

@@ -16,24 +16,6 @@
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 """
 
-# Margin before and after a clip (in seconds)
-clip_margin = 0.4
-assert clip_margin >= 0.0
-
-# How loud should noise be to be considered a sound?
-audio_treshold = 0.01
-assert audio_treshold > 0.0 and audio_treshold <= 1.0
-
-# Minimum clip length (in seconds)
-# Sounds shorter than that will be considered noise and cut.
-min_clip_length = 0.2
-assert min_clip_length > 0.0
-
-# Minimum silence length to skip (in seconds)
-min_skip_length = 2.0
-assert min_skip_length > 2 * clip_margin
-
-
 import audioop
 import subprocess
 import sys
@@ -67,6 +49,16 @@ if __name__ == "__main__":
     filename = sys.argv[1]
     minute = sys.argv[2]
 
+    # Values configurable in cutitout.lua
+    clip_margin = float(sys.argv[3])
+    assert clip_margin >= 0.0
+    audio_treshold = float(sys.argv[4])
+    assert audio_treshold > 0.0 and audio_treshold <= 1.0
+    min_clip_length = float(sys.argv[5])
+    assert min_clip_length > 0.0
+    min_skip_length = float(sys.argv[6])
+    assert min_skip_length > 2 * clip_margin
+
     # Offset in seconds, at which we start searching for skips
     start_offset = float(sys.argv[2]) * 60.0
 
@@ -110,7 +102,7 @@ if __name__ == "__main__":
     if orig_audio.stdout is None:
         raise Exception("Failed to start ffmpeg. Is it installed?")
 
-    clips = []
+    clips: List[Tuple[float, float]] = []
     clip_index = 0
     loud_start = -1
 
@@ -124,7 +116,7 @@ if __name__ == "__main__":
         elif loud_start != -1 and volume < audio_treshold:
             # Remove sounds that are too short to be important
             if clip_index - loud_start > min_clip_length * 100:
-                clips.append((loud_start, clip_index))
+                clips.append((loud_start / 100, clip_index / 100))
             loud_start = -1
 
         chunk_data = orig_audio.stdout.read(fragment_length)
@@ -132,21 +124,20 @@ if __name__ == "__main__":
 
     # Turn clips into skips
     skips: List[Tuple[float, float]] = []
-    last_skip = 0.0
-    index_to_time = lambda index: index / 100
+    current_time = 0.0
     for clip in clips:
-        clip_start = index_to_time(clip[0])
-        clip_end = index_to_time(clip[1])
+        clip_start = clip[0]
+        clip_end = clip[1]
 
-        if clip_start - last_skip < min_skip_length:
-            last_skip = clip_end + clip_margin
+        if clip_start - current_time < min_skip_length:
+            current_time = clip_end + clip_margin
         else:
-            skips.append((last_skip, clip_start - clip_margin))
-            last_skip = clip_end + clip_margin
+            skips.append((current_time, clip_start - clip_margin))
+            current_time = clip_end + clip_margin
 
-    if 1.0 - last_skip >= min_skip_length:
-        skips.append((last_skip, 1.0))
+    if 60.0 - current_time >= min_skip_length:
+        skips.append((current_time, 60.0))
 
     skips = [(start_offset + s[0], start_offset + s[1]) for s in skips]
-    skip_table = ["{" + f"{v[0]},{v[1]}" + "}" for v in skips]
+    skip_table = ["{" + f"{s[0]},{s[1]}" + "}" for s in skips]
     print("return {" + ",".join(skip_table) + "}")

+ 1 - 0
cutitout_shared/main.lua

@@ -0,0 +1 @@
+-- This file exists to avoid MPV reporting errors