2017-03-13 2 views
0

Meine App (in Python) lädt die Gstreamer-Bibliothek, analysiert und startet eine Pipeline-Spezifikation, die Untertitel aus einer SRT-Datei über einem vorbereiteten Video aus einer MP4-Datei zusammenfügt und anschließend ein Steuerelement erstellt Quelle mit einer Bindung an die "Alpha" -Eigenschaft des Sinkpads des Videomixers Elements, das mit der Untertitelbildquelle verknüpft ist.InterpolationControlSource mit Gst.parse_launch()

Zuerst schrieb ich eine kleine proof-of-concept, die wie ein Champion funktioniert. Wenn Sie es mit einem X-Windows-Server (beispielsweise unter Unix oder Linux) ausführen können, sehen Sie ein schwarzes Quadrat auf grünem Hintergrund. Nach einer Sekunde verblasst das schwarze Quadrat allmählich über mehrere Sekunden.

Meine App hat eine Pipeline, die ein bisschen komplexer ist. Im Folgenden finden Sie eine Zusammenfassung der relevanten Code:

pipeline_spec = ''' 
videomixer name=mixer ! ... other stuff downstream 
filesrc location=sample_videos/my-video.mp4 ! decodebin name=demuxer ! mixer.sink_0 
filesrc location=subtitles.srt ! subparse ! textrender ! mixer.sink_1 
demuxer. ! audioconvert ! audioresample ! faac ! muxer. 
''' 

self.pipeline = Gst.parse_launch(pipeline_spec) 
mixer = self.pipeline.get_by_name('mixer') 
#vidpad = mixer.get_static_pad('sink_0') 
srtpad = mixer.get_static_pad('sink_1') 
self.logger.debug([ pad.name for pad in mixer.pads ]) 

cs = GstController.InterpolationControlSource() 
cs.set_property('mode', GstController.InterpolationMode.LINEAR) 
binding = GstController.DirectControlBinding.new(srtpad, 'alpha', cs) 
cs.add_control_binding(binding) 

with open(srtfilepath) as srtfile: 
    for timestamps in parsesrt.parse(srtfile): 
     start, end = timestamps 
     self._set_subtitle_fade(alpha_cs, start, end) 

def _set_fade_effect(self, controlsource, start, duration, alpha_begin, alpha_end): 
    controlsource.set(start, alpha_begin) 
    controlsource.set(start + duration, alpha_end) 
    self.logger.debug('set fade-{0} from {1} to {2}'.format('in' if alpha_begin < alpha_end else 'out', start, start + duration)) 

def _set_subtitle_fade(self, controlsource, start_subtitle, end_subtitle): 
    self._set_fade_effect(controlsource, start_subtitle, self.DURATION_FADEIN, 0, 1) 
    self._set_fade_effect(controlsource, end_subtitle - self.DURATION_FADEOUT, self.DURATION_FADEOUT, 1, 0) 

Ein Unterschied zwischen den beiden Pipelines ist, dass im ersten Beispiel die Videomixer Pads Anfrage Pads sind. Aber in der realen App entpuppen sie sich als statische Pads. Und nur "Senke_1" ist in der Log-Anweisung vorhanden.

DEBUG, ['src', 'sink_1'] 

Ich bin mir nicht sicher, warum das so ist oder ob es einen Unterschied macht.

Wenn ich die App auf einem Webserver starte und in einem Browser einchecke, erscheinen die Untertitel, aber sie werden nicht ein- oder ausgeblendet.

Ich überprüfte die Zeitstempel und sie sehen gut aus. Sie sind in Nanosekunden (10^9).

set fade-in from 2440000000 to 3440000000 
set fade-out from 2375000000 to 4375000000 
set fade-in from 7476000000 to 8476000000 
... 

Also welchen Stein habe ich unausgeschieden?

Antwort

0

Der andere große Unterschied zwischen Ihrem ersten und zweiten Prototypen ist videotestsrc, der zu filesrc ! decodebin wechselt. gst_parse_launch verbindet nicht sofort decodebin mit videomixer. Was wird passieren, ist dies:

  • Pipeline analysiert wird aber decodebin weiß nicht, den Inhalt von filesrc bis es de-Multiplexern es. Es könnte Audio oder eine Powerpoint-Präsentation oder eine PGP-Signatur oder irgendetwas sein. Es gibt also zunächst keine Quell-Pads zurück.

  • Sie spielen die Pipeline. decodebin beginnt Daten von filesrc zu empfangen, identifiziert den Inhalt als mp4 und demuxiert es. Es stellt fest, dass es Videoinhalte hat, die Pads für videomixer entsprechen, und stellt die Verbindung zum ersten offenen Pad her.

Also, was Sie wahrscheinlich tun müssen, ist für das Pad-added-Ereignis auf decodebin zu hören, prüfen Sie, ob es die richtige Unterlage ist, und dann machen Sie Ihre Bindung.

def decodebin_pad_added(self, decodebin, pad): 
    #return if pad is wrong type 

    #make the binding to the pad 

decodebin.connect("pad_added", decodebin_pad_added) 

können Sie wissen, dass dieses Verhalten durch Ausführen gst-inspect-1.0 auf dem betreffenden Element und der Prüfung der Pads vorhanden sein wird. Sie können sehen, dass decoderbin hat eine "manchmal" Pad-Vorlage im Vergleich zu einem konstanten Pad, das auf subparse vorhanden ist:

+0

Vielen Dank @mpr! Ich werde es versuchen, dann melde ich mich wieder bei dir. –

+0

gst-inspect decoderbin zeigt alle möglichen nützlichen Eigenschaften, wie das Pad-Add-Signal. Aber welche Version von gst-plugins-base hast du. In meiner Version wird "custom eventfunc()" für das Pad subparse.src nicht angezeigt. Ich benutze Version 1.8.1 der Plugins. –

+0

Ich bin auf 1.6. Ich bin mir nicht sicher, ob Sie sich über diese benutzerdefinierten Funktionen Gedanken machen müssen, sondern dass sie nur informativ sind. – mpr