3

今日、いくつかの機能を追加するために、 に基づく小さなスクリプトをgst-launch実際の Python/GStreamer アプリケーションに変換することにしました。

のおかげで、マイクからオーディオを Icecast ( shout2send) とローカル ストレージ ( ) の両方に送信する小さなプログラムを開発しました。filesinktee

shout2sendネットワークの問題により、時々停止することがあります。ローカル オーディオ ファイルはネットワーク状態の影響を受けないため、パイプラインを停止せずに、接続が回復するまで N 秒ごとにこの要素を再起動したいと考えています。

これが私が試したことです:

  1. ネットワーク エラーの 1 秒後にパイプラインを停止/開始する (結果: ストリーミングは機能し、ローカル ファイルは切り詰められます)
  2. からリンクを解除し、状態をパイプラインteeに設定し、パイプラインから削除します (結果: のような GStreamer の重大なエラー)shout2sendNULLTrying to dispose element ... but it is in PLAYING instead of the NULL state
  3. この場合のパッドの使用方法を理解しようとしています (結果: 上記と同じですが、より多くのコードが含まれます)

私は何をすべきか?

私のコードは次のようになります。

import gi
gi.require_version("Gst", "1.0")
from gi.repository import GLib
from gi.repository import Gst
# [...]

def message_handler(bus, message):
    if message.type == Gst.MessageType.ERROR:
        if message.src == shout2send:
            pass # TODO: restart the element
        else:
            print(message.parse_error())
            pipeline.set_state(Gst.State.NULL)
            exit(1)
    else:
        print(message.type)

pipeline = Gst.Pipeline()
message_bus = pipeline.get_bus()
message_bus.add_signal_watch()
message_bus.connect('message', message_handler)

# [...]
tee.link(queue0)
queue0.link(filesink)
tee.link(queue1)
queue1.link(shout2send)

更新 (2015 年 9 月 12 日) : 非動作コードの追加 + ログ

GStreamer doc の「パイプラインを動的に変更する」に従おうとしましたが、コードが機能しません。

def event_probe(pad, info, *args):
    Gst.Pad.remove_probe(pad, info)
    queue1.unlink(shout2send)
    tee.unlink(queue1)
    pipeline.remove(shout2send)
    pipeline.remove(queue1)
    return Gst.PadProbeReturn.OK

def message_handler(bus, message):
    if message.type == Gst.MessageType.ERROR:
        if message.src == shout2send:
            pad = queue1.get_static_pad('src')
            pad.add_probe(Gst.PadProbeType.BLOCK_DOWNSTREAM, event_probe, None)
        else:
            print(message.parse_error())
            pipeline.set_state(Gst.State.NULL)
            exit(1)
    else:
        print(message.type)

スクリプトを実行し、GST_DEBUG=3ストリーミング中に Icecast を再起動すると、次のようになります。

[...]
0:00:02.142033258  5462 0x55e414d900a0 WARN                  shout2 gstshout2.c:674:gst_shout2send_render:<shout2send> error: shout_send() failed: Socket error
0:00:02.658137998  5462 0x55e414d90140 WARN                 basesrc gstbasesrc.c:2943:gst_base_src_loop:<pulsesrc> error: Internal data flow error.
0:00:02.658169752  5462 0x55e414d90140 WARN                 basesrc gstbasesrc.c:2943:gst_base_src_loop:<pulsesrc> error: streaming task paused, reason error (-5)
(GLib.Error('Internal data flow error.', 'gst-stream-error-quark', 1), 'gstbasesrc.c(2943): gst_base_src_loop (): /GstPipeline:pipeline0/GstPulseSrc:pulsesrc:\nstreaming task paused, reason error (-5)')
0:00:02.658628129  5462 0x7f6ba8002a30 WARN                audiosrc gstaudiosrc.c:244:audioringbuffer_thread_func:<pulsesrc> error reading data -1 (reason: Success), skipping segment
4

1 に答える 1