Closed seandenigris closed 2 years ago
Neat idea! Here's a slightly simpler version that uses the wait_for_event method that I've recently added on master:
#!/usr/bin/env python3
import sys
import mpv
p = mpv.MPV()
p.play(sys.argv[1])
def skip_silence():
p.set_loglevel('debug')
p.af = 'lavfi=[silencedetect=n=-20dB:d=1]'
p.speed = 100
def check(evt):
toks = evt['event']['text'].split()
if 'silence_end:' in toks:
return float(toks[2])
p.time_pos = p.wait_for_event('log_message', cond=check)
p.speed = 1
p.af = ''
skip_silence()
p.wait_for_playback()
I think I'll include this in a future release. The only thing I don't like about it right now is that it has to change the instance's log level. We could theoretically avoid that by cloning the MPV handle, but that might be a bit too complex to include in python-mpv.
Thanks for the feedback! I'm not a Python programmer, but the Smalltalk-inspired platformI use, GToolkit, supports Python and its countless cool libraries - including yours :) I cobbled it together due to necessity from SO posts, so feel free to improve/use it any way you see fit.
I tried to test this version, but from:
p.time_pos = p.wait_for_event('log_message', cond=check)
I'm getting TypeError: ('Tried to get/set mpv property using wrong format, or passed invalid value', -9, (<MpvHandle object at 0x10140b0c0>, b'time-pos', b'None'))
This is what I finally ended up with based on your feedback:
def skip_silence(self, noise=-40, duration=1):
self.set_loglevel('v')
endPosition = None
def is_silence_end(evt):
nonlocal endPosition
toks = evt['event']['text'].split()
if 'silence_start:' in toks:
self.speed = 100
elif 'silence_end:' in toks:
endPosition = float(toks[2])
return True
return False
with self.prepare_and_wait_for_event('log_message', cond=is_silence_end):
self.af = 'lavfi=[silencedetect=n=' + str(noise) + 'dB:d=' + str(duration) + ']'
self.time_pos = endPosition
self.speed = 1
self.af = ''
mpv.MPV.skip_silence = skip_silence
One thing it took me a while to figure out was that the block of with self.prepare_and_wait_for_event(...):
is where you put the thing that might potentially trigger the event. It was alluded to in the source docs, but IMHO could use some clarification. Also, prepare_and_wait_for_event
seems to return a value, but I couldn't figure out how to access it. I tried to put an assignment to the left of the with
but got a syntax error.
Thank you for the example! The README now contains this code in the example usage section. I will publish a release soon that contains the new futures API that is used there.
This extension to skip silence might be of interest for adaptation and inclusion in mpv proper. Here is a usage example.