savonet / liquidsoap

Liquidsoap is a statically typed scripting general-purpose language with dedicated operators and backend for all thing media, streaming, file generation, automation, HTTP backend and more.
http://liquidsoap.info
GNU General Public License v2.0
1.4k stars 128 forks source link

Gstreamer RTMP freezes #1020

Open eirenik0 opened 4 years ago

eirenik0 commented 4 years ago

Describe the bug I'm trying to build the script that combine rtmp VA with http audio based on some rules. I've made it work, but the actual script doesn't work stable. I use gstreamer to receive AV and audio. After several minutes of work the AV un-sync become visible. The image freezes from time to time. And in the end the RTMP stream stops. The log says Restarting pipeline but no restart happening actually.

Also, I can close the liquidsoap only with kill command at the end.

To Reproduce

set("frame.video.height", 1080)
set("frame.video.samplerate", 30)
set("frame.audio.samplerate", 48000)
set("gstreamer.add_borders", false)
set("clock.allow_streaming_errors", false)

origin_video_stream_address = "rtmp://0.0.0.0:1935/live_output/stream"
stream_to_server_address = "rtmp://0.0.0.0:1935/live_en/stream"
icecast_audio_address= "http://0.0.0.0:7800/en"

audio_trans = mksafe(
        input.gstreamer.audio(
          pipeline="uridecodebin uri=#{icecast_audio_address}"
    )
)

origin_video_stream = mksafe(input.gstreamer.audio_video(
    pipeline="rtmpsrc location=#{origin_video_stream_address} ! tee name=t",
    audio_pipeline="t. ! queue",
    video_pipeline="t. ! queue"
    )
)

stream = mux_video(
        video=drop_audio(origin_video_stream),
        add([drop_video(origin_video_stream), audio_trans])
)

output = output.gstreamer.audio_video(
        video_pipeline="videoconvert ! x264enc bitrate=5000 tune=zerolatency pass=17 ! video/x-h264,profile=main ! queue ! mux.",
        audio_pipeline="audioconvert ! voaacenc bitrate=128 ! queue ! mux.",
        pipeline="flvmux streamable=true name=mux ! rtmpsink location=\"#{stream_to_server_address} live=1\"",
        stream
)

Expected behavior The script should work without AV sync diff and restart output if some error happens.

Version details

Install method OPAM installation

The actual log:

GST_DEBUG="*:2" liquidsoap /etc/nginx/scripts/stream_lang.liq
2019/11/03 02:21:51 >>> LOG START
2019/11/03 02:21:51 [main:3] Liquidsoap 1.4.0
2019/11/03 02:21:51 [main:3] Using: bytes=[distributed with OCaml 4.02 or above] pcre=7.4.3 sedlex=2.1 menhirLib=20190924 dtools=0.4.1 duppy=0.8.0 cry=0.6.4 mm=0.5.0 ogg=0.5.2 vorbis=0.7.1 opus=0.1.3 mad=0.4.5 flac=0.1.5 flac.ogg=0.1.5 dynlink=[distributed with Ocaml] lame=0.3.3 gstreamer=0.3.0 fdkaac=0.3.1 theora=0.3.1 gavl=0.1.6 samplerate=0.1.4 taglib=0.3.6 camomile=1.0.2 faad=0.4.0
2019/11/03 02:21:51 [gstreamer.loader:3] Loaded GStreamer 1.14.5 0
2019/11/03 02:21:51 [harbor:3] Adding handler for 'GET ^/api/isOriginLang' on port 8005
2019/11/03 02:21:51 [harbor:3] Adding handler for 'PUT ^/api/changeLang' on port 8005
2019/11/03 02:21:51 [lang:3] Create translation audio stream http://0.0.0.0:7800/en
2019/11/03 02:21:51 [frame:3] Using 48000Hz audio, 30Hz video, 48000Hz master.
2019/11/03 02:21:51 [frame:3] Frame size must be a multiple of 1600 ticks = 1600 audio samples = 1 video samples.
2019/11/03 02:21:51 [frame:3] Targetting 'frame.duration': 0.04s = 1920 audio samples = 1920 ticks.
2019/11/03 02:21:51 [frame:3] Frames last 0.07s = 3200 audio samples = 2 video samples = 3200 ticks.
2019/11/03 02:21:51 [lang:3] Trans audio stream initialized: <source>
2019/11/03 02:21:51 [lang:3] Receive stream from rtmp://0.0.0.0:1935/live_output/stream
2019/11/03 02:21:51 [lang:3] Origin video stream initialized: <source>
2019/11/03 02:21:51 [lang:3] Make mixed audio stream for en
2019/11/03 02:21:51 [lang:3] Mixed audio stream initialized: <source>
2019/11/03 02:21:51 [lang:3] Output source: <source>
2019/11/03 02:21:51 [lang:3] Stream to rtmp://0.0.0.0:1935/live_en/stream
2019/11/03 02:21:51 [sandbox:3] Sandboxing disabled
2019/11/03 02:21:51 [video.converter:3] Using preferred video converter: gavl.
2019/11/03 02:21:51 [audio.converter:3] Using samplerate converter: libsamplerate.
0:00:15.590166262 10929 0x7fb4f4070b70 WARN                flvdemux gstflvdemux.c:659:gst_flv_demux_parse_tag_script:<flvdemux0> failed reading a tag, skipping
0:00:15.590169017 10929 0x7fb4f4070800 WARN                flvdemux gstflvdemux.c:659:gst_flv_demux_parse_tag_script:<flvdemux1> failed reading a tag, skipping
0:00:16.443160873 10929 0x7fb4d4055680 WARN         audio-resampler audio-resampler.c:274:convert_taps_gint16_c: can't find exact taps
0:00:16.887173223 10929 0x7fb4545fdf20 WARN         audio-resampler audio-resampler.c:274:convert_taps_gint16_c: can't find exact taps
2019/11/03 02:22:08 [clock.wallclock_gstreamer:3] Streaming loop starts, synchronized by active sources.
2019/11/03 02:22:08 [en:3] Switch to add_7788.
2019/11/03 02:22:08 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779.
2019/11/03 02:22:08 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771.
2019/11/03 02:22:08 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:08 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:08 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:08 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:08 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:08 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:09 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:10 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:10 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:10 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:10 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:10 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:10 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:10 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:10 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:11 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:11 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:11 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:11 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:11 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:11 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:11 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:11 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:22:12 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:12 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:12 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:12 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:12 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:12 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:22:24 [en:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:22:25 [en:3] Switch to input(dot)gstreamer(dot)audio_video_7771 with transition.
2019/11/03 02:23:00 [en:3] Switch to drop_video_7785 with transition.
2019/11/03 02:23:15 [en:3] Switch to add_7788 with transition.
2019/11/03 02:23:32 [en:3] Switch to drop_video_7785 with transition.
2019/11/03 02:26:22 [mksafe:3] Switch to safe_blank with transition.
2019/11/03 02:26:22 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:26:22 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:26:23 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:26:32 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:26:33 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
2019/11/03 02:26:34 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/03 02:26:35 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7779 with transition.
0:10:14.301001889 10929 0x5613aabeaa30 ERROR                   rtmp :0:: WriteN, RTMP send error 32 (129 bytes)
0:10:14.301198926 10929 0x5613aabeaa30 ERROR                   rtmp :0:: WriteN, RTMP send error 32 (41 bytes)
0:10:14.301289863 10929 0x5613aabeaa30 ERROR                   rtmp :0:: WriteN, RTMP send error 9 (42 bytes)
0:10:14.301326446 10929 0x5613aabeaa30 WARN                rtmpsink gstrtmpsink.c:286:gst_rtmp_sink_render:<rtmpsink0> error: Failed to write data
2019/11/03 02:32:06 [output(dot)gstreamer:2] [rtmpsink0] Error: Could not write to resource.
2019/11/03 02:32:06 [output(dot)gstreamer:3] Error while processing output data: Could not write to resource.
0:10:15.568053917 10929 0x5613aadfaa30 WARN                 basesrc gstbasesrc.c:3055:gst_base_src_loop:<audio_src> error: Internal data stream error.
0:10:15.568203900 10929 0x5613aadfaa30 WARN                 basesrc gstbasesrc.c:3055:gst_base_src_loop:<audio_src> error: streaming stopped, reason error (-5)
0:10:15.569348155 10929 0x5613aadfaa30 WARN                   queue gstqueue.c:988:gst_queue_handle_sink_event:<queue3> error: Internal data stream error.
0:10:15.569399525 10929 0x5613aadfaa30 WARN                   queue gstqueue.c:988:gst_queue_handle_sink_event:<queue3> error: streaming stopped, reason error (-5)
0:10:16.181844899 10929 0x5613aadfa8a0 WARN                 basesrc gstbasesrc.c:3055:gst_base_src_loop:<video_src> error: Internal data stream error.
0:10:16.181920849 10929 0x5613aadfa8a0 WARN                 basesrc gstbasesrc.c:3055:gst_base_src_loop:<video_src> error: streaming stopped, reason error (-5)
0:10:16.182055560 10929 0x5613aadfa8a0 WARN                   queue gstqueue.c:988:gst_queue_handle_sink_event:<queue2> error: Internal data stream error.
0:10:16.182081479 10929 0x5613aadfa8a0 WARN                   queue gstqueue.c:988:gst_queue_handle_sink_event:<queue2> error: streaming stopped, reason error (-5)
2019/11/03 02:32:07 [output(dot)gstreamer:2] [audio_src] Error: Internal data stream error.
2019/11/03 02:32:07 [output(dot)gstreamer:3] Error while processing output data: Internal data stream error.
2019/11/03 02:32:10 [output(dot)gstreamer:3] Restarting pipeline
smimram commented 4 years ago

Could you first try to replace the output, by a local output, e.g.

output.sdl(drop_audio(stream))
out(stream)

and tell us if there are problems? (I am trying to first guess whether the culprit is the input, the output or both...)

eirenik0 commented 4 years ago

Thanks for fast answer @smimram !

I'm trying to run with sdl but got following error: Error 4: Undefined variable output.sdl

I've installed sdl2 package to system and tsdl package to opam but has no difference. Also, I didn't find any description in docs about installing of sdl.

Anyway, I've commented output.sdl line and run only with audio and seems it has frozen after similar time gap. It starts from audio issues, the voice is becoming steep and then it complety froozes. But I don't see any output error and I can close program easily. So seems the output.gstreamer.audio_video has prevents normal program closing, but the root of issue is in input somewhere.

smimram commented 4 years ago

You should opam install ocamlsdl.

smimram commented 4 years ago

Another thing to try is output.gstreamer.audio_video(stream), which should also play your stream (but using GStreamer).

eirenik0 commented 4 years ago

Interesting, regarding opam install ocamlsdl after installing this lib the liquidsoap by itself doesn't want to compile.

The output.gstreamer.audio_video(stream) doesn't work too. I cannot manage it to work. I'm getting following issue: 0:00:02.556340000 97199 0x7f92c25a1960 ERROR gldisplay gstgldisplay_cocoa.m:171:GstGLDisplayCocoa *gst_gl_display_cocoa_setup_nsapp(gpointer): Custom NSApp initialization failed 0:00:02.556369000 97199 0x7f92c25a1960 ERROR glutils gstglutils.c:229:void gst_gl_element_propagate_display_context(GstElement *, GstGLDisplay *):<sink> Could not get GL display connection

autonarcosis commented 4 years ago

I suspect there are multiple issues here.

I have found when using LS and GStreamer and attempting to exit with control-c and it locks up, requiring a kill. There is something not right with the GStreamer pipeline. Which seems to be indicated via the log file that you originally posted. Be sure to use the GStreamer debug level setting to get more information from GStreamer.

set("gstreamer.debug_level",2)

I have never cracked the audio desync issue in LS. Unless the developers finally after 5 years acknowledge this issue, it most likely will never work. It only took several years to get the internal video working so that we could use ffmpeg.

So what I have found is that, the source video must all have the same framerate set to LS. So for example the default framerate is 25. All source videos must be 25fps. Any deviation will immediately cause audio desynchronization in the transition from one file to the next.

In your example script, I am not sure there is anyway to ever reliably have the audio synchronized with the video. What you are doing is taking an rtmp source and an icecast source, dropping the audio from the rtmp and adding the icecast source, then encoding it out via rtmp. Any sort of latency in either of the input streams would be an immediate cascading failure. Both methods transmit data differently and have different buffering methods, especially the Icecast server which is usually a good 30 seconds or so.

Unless I've completely misunderstood the issue. If the issue is just things locking up, I suggest using gst-launch-1.0 and creating a big ass albeit torturous command line pipeline that does exactly the same thing. Then once you get the working pipeline down you can start migrating it into the LS script.

I also recommend if possible. Upgrade to v1.16 of GStreamer. I do understand that is an entire different rabbit hole of hell.

autonarcosis commented 4 years ago

After attempting to re-create your scenario. There is definitely a bug in the input functionality using GStreamer. Not just in the input.gstreamer.audio_video but the input.gstreamer.video function as well. Although I suspect they essentially are the same thing. Also, I suspect there is also an issue that I believe you are using the input.gstreamer.audio_video function in an unintentional way. Although with the current non-functionality of it, it's hard to tell.

To reproduce this error you'll need three terminals.

Start ffmpeg in one terminal as the source rtmp service;

$ ffmpeg -re -i /path/to/some/video/file.avi -f flv -listen 1 rtmp://127.0.0.1:1935/live/app

Start ffmpeg in another terminal to accept the output rtmp stream (notice I am using different ports);

$ ffmpeg -f flv -listen 1 -i rtmp://127.0.0.1:1945/live/app -c copy test.flv

The modifications I made to the original script;

#Define playlists
videoplaylist = (input.gstreamer.video(
        pipeline="rtmpsrc location=\"rtmp://127.0.0.1:1935/live/app\""
))

audioplaylist = (input.gstreamer.audio(
        pipeline="audiotestsrc"
))

stream = mux_video(video=videoplaylist,audioplaylist)

stream = mksafe(stream)

output.gstreamer.audio_video(
        video_pipeline="videoconvert ! x264enc bitrate=1024 pass=qual qualtizer=20 tune=zerolatency speed-preset=ultrafast ! video/x-h264,profile=baseline,stream-format=avc ! queue ! muxer.",
        audio_pipeline="audioconvert ! fdkaacenc bitrate=64000 ! audio/mpeg, mpegversion=4 ! queue ! muxer.",
        pipeline="flvmux streamable=true name=muxer ! rtmpsink location=\"rtmp://127.0.0.1:1945/live/app\"",
        stream)

LS Logfile;

$ liquidsoap videortmpgstreamertest.liq 
0:00:00.000080960  6133      0x18b3800 INFO                GST_INIT gst.c:586:init_pre: Initializing GStreamer Core Library version 1.16.0
0:00:00.000151440  6133      0x18b3800 INFO                GST_INIT gst.c:587:init_pre: Using library installed in /usr/lib64
0:00:00.000203119  6133      0x18b3800 INFO                GST_INIT gst.c:605:init_pre: Linux banana3000.autonarcosis.com 5.3.7-200.fc30.x86_64 #1 SMP Fri Oct 18 20:13:59 UTC 2019 x86_64
2019/11/04 17:22:36 >>> LOG START
2019/11/04 17:22:36 [main:3] Liquidsoap 1.4.0
2019/11/04 17:22:36 [main:3] Using: bytes=[distributed with OCaml 4.02 or above] pcre=7.4.3 sedlex=2.1 menhirLib=20190924 dtools=0.4.1 duppy=0.8.0 cry=0.6.4 mm=0.5.0 ogg=0.5.2 vorbis=0.7.1 mad=0.4.5 flac=0.1.5 flac.ogg=0.1.5 dynlink=[distributed with Ocaml] lame=0.3.3 gstreamer=0.3.0 frei0r=0.1.1 fdkaac=0.3.2 theora=0.3.1 gavl=0.1.6 ffmpeg=0.4.1 alsa=0.2.3 ao=0.2.1 samplerate=0.1.4 taglib=0.3.6 camomile=1.0.2 ladspa=0.1.5 gd=1.0a5
2019/11/04 17:22:36 [gstreamer.loader:3] Loaded GStreamer 1.16.0 0
2019/11/04 17:22:36 [lang:2] WARNING: there is no configuration key named "gstreamer.debug_level"!
2019/11/04 17:22:36 [frame:3] Using 44100Hz audio, 25Hz video, 44100Hz master.
2019/11/04 17:22:36 [frame:3] Frame size must be a multiple of 1764 ticks = 1764 audio samples = 1 video samples.
2019/11/04 17:22:36 [frame:3] Targetting 'frame.duration': 0.04s = 1764 audio samples = 1764 ticks.
2019/11/04 17:22:36 [frame:3] Frames last 0.04s = 1764 audio samples = 1 video samples = 1764 ticks.
2019/11/04 17:22:36 [sandbox:3] Sandboxing disabled
2019/11/04 17:22:36 [video.converter:3] Using preferred video converter: gavl.
2019/11/04 17:22:36 [threads:4] Created thread "gstreamer_main_loop" (1 total).
2019/11/04 17:22:36 [audio.converter:3] Using samplerate converter: ffmpeg.
2019/11/04 17:22:36 [threads:4] Created thread "generic queue #1" (1 total).
2019/11/04 17:22:36 [threads:4] Created thread "generic queue #2" (2 total).
2019/11/04 17:22:36 [threads:4] Created thread "non-blocking queue #1" (3 total).
2019/11/04 17:22:36 [threads:4] Created thread "non-blocking queue #2" (4 total).
2019/11/04 17:22:36 [clock:4] Currently 1 clocks allocated.
2019/11/04 17:22:36 [clock.wallclock_gstreamer:4] Starting 1 sources...
2019/11/04 17:22:36 [source:4] Source gstreamer_8167 gets up.
2019/11/04 17:22:36 [source:4] Source mksafe gets up.
2019/11/04 17:22:36 [source:4] Source mux_8162 gets up.
2019/11/04 17:22:36 [mux_8162:4] Content kind is {audio=2;video=1;midi=0}.
2019/11/04 17:22:36 [source:4] Source input.gstreamer.audio_video_8160 gets up.
2019/11/04 17:22:36 [input.gstreamer.audio_video_8160:4] Content kind is {audio=2;video=0;midi=0}.
2019/11/04 17:22:36 [io.gstreamer:5] GStreamer pipeline:  audiotestsrc ! decodebin ! audioconvert ! audioresample ! appsink max-buffers=10 drop=false sync=false name="audio_sink" caps="audio/x-raw,format=S16LE,layout=interleaved,channels=2,rate=44100"
2019/11/04 17:22:36 [input(dot)gstreamer(dot)audio_video_8160:4] Activations changed: static=[mux_8162:mksafe:output(dot)gstreamer:output(dot)gstreamer], dynamic=[].
2019/11/04 17:22:36 [source:4] Source input.gstreamer.audio_video_8158 gets up.
2019/11/04 17:22:36 [input.gstreamer.audio_video_8158:4] Content kind is {audio=0;video=1;midi=0}.
2019/11/04 17:22:36 [io.gstreamer:5] GStreamer pipeline:  rtmpsrc location="rtmp://banana3000.autonarcosis.com:1935/live/app" ! decodebin ! videoconvert ! videoscale add-borders=true ! videorate ! appsink name="video_sink" drop=false sync=false max-buffers=10 caps="video/x-raw,format=RGBA,width=512,height=384,framerate=25/1,pixel-aspect-ratio=1/1"

ERROR: Caught a segmentation fault while loading plugin file:
/usr/lib64/gstreamer-1.0/libgstlibav.so

Please either:
- remove it and restart.
- run with --gst-disable-segtrap --gst-disable-registry-fork and debug.
$

If you take the rtmpsrc pipeline, restart the ffmpeg rtmp source and run it through gst-launch, it will work.

gst-launch-1.0 rtmpsrc location="rtmp://banana3000.autonarcosis.com:1935/live/app" ! decodebin ! videoconvert ! videoscale add-borders=true ! videorate ! appsink name="video_sink" drop=false sync=false max-buffers=10 caps="video/x-raw,format=RGBA,width=512,height=384,framerate=25/1,pixel-aspect-ratio=1/1"

I'll post an ffmpeg solution tomorrow. My brain is too fried.

eirenik0 commented 4 years ago

@autonarcosis thanks for your efforts!

I think it's different issues. I've had this issue when my libraries were installed in wrong way. It happens with apt installation. After I've installed everything with opam this error has been gone.

By the way, on macos there gstreamer 1.16.1 version already

eirenik0 commented 4 years ago

@autonarcosis I've tested with your settings. There the same issue with AV drift and blank screen with no audio after 10 minutes. But now RTMP stream not ends. It's going with blank screen and no audio. So I think the issue here is somewhere inside gstreamer input part.

eirenik0 commented 4 years ago

Also, input periodically lost stream and switch to blank:

2019/11/05 10:41:34 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/05 10:41:34 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7697 with transition.
2019/11/05 10:41:34 [mksafe:3] Switch to safe_blank with forgetful transition.
2019/11/05 10:41:34 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_7697 with transition.

So it's definitely something with input function. Because I've used to stream mp4 to rtmp and I didn't have such amount of issues here. Need to try use ffmpeg encoder for input

autonarcosis commented 4 years ago

For ffmpeg just replace your rtmp input line with something like this;

videoplaylist = (input.external.ffmpeg("-loglevel quiet -i rtmp://127.0.0.1:1935/live/app" )

autonarcosis commented 4 years ago

There is definitely something wrong with the gstreamer plugin.

After recompiling liquidsoap to do these tests, then going back to my generic radio station script that just plays audio files outputting to an icecast server using fdkaac I am getting the same segmentation fault. There are no calls to gstreamer within the script, such as input or output. Looks like a wma file may have triggered it but I don't have time to test it tonight.

2019/11/06 00:13:28 [decoder:3] Method "FFMPEG" accepted "/home/geoff/Music/Techno/Parasols Volume One (1993)/08 - Wild West - Citric.wma". 2019/11/06 00:13:29 [stdout:3] 2019/11/06 00:13:29 [stdout:3] ERROR: Caught a segmentation fault while loading plugin file: 2019/11/06 00:13:29 [stdout:3] /usr/lib64/gstreamer-1.0/libgstlibav.so 2019/11/06 00:13:29 [stdout:3] 2019/11/06 00:13:29 [stdout:3] Please either: 2019/11/06 00:13:29 [stdout:3] - remove it and restart. 2019/11/06 00:13:29 [stdout:3] - run with --gst-disable-segtrap --gst-disable-registry-fork and debug.

eirenik0 commented 4 years ago

@autonarcosis from my experience, you shouldn't use gstreamer and ffmpeg together. Only one library should be installed per time. Try to remove all gstreamer dependencies including gstreamer opam package. It should help

eirenik0 commented 4 years ago

@autonarcosis actually this ffmpeg method works not correct. I use next code:

origin_video_stream = mksafe(input.external.ffmpeg(
          "-i rtmp://0.0.0.0:1935/live_output/stream"
    )
)
output.prefered(origin_video_stream)

I've gotten next log:

2019/11/20 02:45:34 [clock.wallclock_pa:3] Streaming loop starts, synchronized by active sources.
2019/11/20 02:45:34 [mksafe:3] Switch to safe_blank.
2019/11/20 02:45:38 [mksafe:3] Switch to input(dot)external(dot)avi_8119 with transition.
2019/11/20 02:45:40 [mksafe:3] Switch to safe_blank with transition.
2019/11/20 02:45:40 [mksafe:3] Switch to input(dot)external(dot)avi_8119 with transition.
2019/11/20 02:45:41 [mksafe:3] Switch to safe_blank with transition.
2019/11/20 02:45:41 [mksafe:3] Switch to input(dot)external(dot)avi_8119 with transition.
2019/11/20 02:45:41 [mksafe:3] Switch to safe_blank with transition.
2019/11/20 02:45:42 [mksafe:3] Switch to input(dot)external(dot)avi_8119 with transition.
2019/11/20 02:45:42 [mksafe:3] Switch to safe_blank with transition.

Do you know how to deal with it? Because it unusable now

autonarcosis commented 4 years ago

After doing some brief testing, this is a modified configuration. The max_muxing_queue_size seems to be variable to specific conditions. I highly recommend using the -loglevel debug and it's -report feature which will produce detailed logs of what ffmpeg is doing. Once it's working you can do -loglevel quiet to stop ffmpeg from outputting information in the Liquidsoap logfile.;

videoplaylist = (input.external.ffmpeg("-loglevel debug -report -i rtmp://127.0.0.1:1935/live/app -max_muxing_queue_size 1024"))

autonarcosis commented 4 years ago

As a side note. I created a similar scenario where I take a source from an rtmp audio/video stream and an Icecast audio stream, then drop the audio from the A/V stream, and add the Icecast audio to the video stream. I also get random switching to the mksafe blank. It only occurs in the first few minutes and then occurs about every 3 minutes very quickly. I can't pinpoint where or why this is occurring.

eirenik0 commented 4 years ago

@autonarcosis could it be related to some buffering of icecast source? Interesting that after I've changed input protocol to http (HLS) the same switching issue is happening. May it be related to some internal stuff of icecast? @toots you're working on ffmpeg now so this issue could be related as well.

autonarcosis commented 4 years ago

Very possible that it's a buffering issue with the icecast source. In order to get a semi-stable working proof of concept I had to modify the buffers of the input icecast source;

audioplaylist = (input.http(buffer=4.,max=30.,"http://127.0.0.1:8000/stream"))

The icecast source is OGG/Vorbis.

I also get these errors for pretty much every frame. It's a bit ambiguous, but I believe that it's a synchronization issue.

2019/11/20 10:06:17 [mux_7432:5] Copy-avoiding optimization isn't working!

toots commented 4 years ago

Hey! Would you be ale to test with the pending ffmpeg-video branch and PR? It now supports streaming to youtube and would be a much better alternative to gstreamer. See this comment: https://github.com/savonet/liquidsoap/pull/1038#issuecomment-559128035