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.42k stars 130 forks source link

issue with send metadata to icecast and shoutcast #2506

Closed wezo3 closed 2 years ago

wezo3 commented 2 years ago

Describe the bug I see when start liquidsoap process from beginning metadata not sent to icecast or shoutcast and send metadata success when start next track for example it I set single file for loop metadata not send when I start liquidsoap and send success in next loop

same issue happen if restart icecast/shoutcast server metadata not sent and send success with next track I hope from developers check this and fix as soon as possible in next update

main post url : https://github.com/savonet/liquidsoap/discussions/2496

To Reproduce A minimal script to reproduce the issue is the most efficient way to have your bug addressed and fixed very quickly!

input = single("/root/media/raj3en_ya_hawa.mp3")
output.icecast( %mp3.cbr(stereo=true,stereo_mode="default",samplerate=44100,bitrate=320,id3v2=true),
name="auto dj",
public=true,
description="test 11",
url="domain.com",
mount="stream",
host="127.0.0.1",
port=8000,
password="passwordhere111",
genre="music1",
fallible=true, input)

Expected behavior when start liquidsoap process from beginning metadata not sent to icecast or shoutcast and send metadata success when start next track

Version details

Install method Installed by opam with all packages

Common issues Can't decode or encode in some audio format? Check if you have installed the correct dependencies i'm sure every thing good because its works good when start next track after first time run

this is the logs :

2022/07/07 14:55:30 >>> LOG START
2022/07/07 14:55:28 [main:3] Liquidsoap 2.0.6
2022/07/07 14:55:28 [main:3] Using: bytes=[distributed with OCaml 4.02 or above] pcre=7.5.0 sedlex=3.0 menhirLib=20220210 curl=0.9.2 dtools=0.4.4 duppy=0.9.2 cry=0.6.7 mm=0.8.1 ogg=0.7.1 ogg.decoder=0.7.1 vorbis=0.8.0 vorbis.decoder=0.8.0 opus=0.2.1 opus.decoder=0.2.1 speex=0.4.1 speex.decoder=0.4.1 mad=0.5.2 flac=0.3.0 flac.ogg=0.3.0 flac.decoder=0.3.0 dynlink=[distributed with Ocaml] lame=0.3.6 fdkaac=0.3.2 ffmpeg=1.1.4 samplerate=0.1.6 taglib=0.3.9 ssl=0.5.9 magic=0.7.3 camomile=1.0.2 faad=0.5.0
2022/07/07 14:55:28 [clock:3] Using builtin (low-precision) implementation for latency control
2022/07/07 14:55:30 [frame:4] frame.audio.channels set to: 2
2022/07/07 14:55:30 [frame:4] frame.video.default set to: false
2022/07/07 14:55:30 [frame:4] frame.midi.channels set to: 0
2022/07/07 14:55:30 [frame:4] frame.video.width set to: 1280
2022/07/07 14:55:30 [frame:4] frame.video.height set to: 720
2022/07/07 14:55:30 [frame:4] frame.audio.samplerate set to: 44100
2022/07/07 14:55:30 [frame:4] frame.video.framerate set to: 25
2022/07/07 14:55:30 [frame:4] frame.audio.samplerate set to: 44100
2022/07/07 14:55:30 [frame:3] Using 44100Hz audio, 25Hz video, 44100Hz main.
2022/07/07 14:55:30 [frame:3] Video frame size set to: 1280x720
2022/07/07 14:55:30 [frame:3] Frame size must be a multiple of 1764 ticks = 1764 audio samples = 1 video samples.
2022/07/07 14:55:30 [frame:3] Targeting 'frame.duration': 0.04s = 1764 audio samples = 1764 ticks.
2022/07/07 14:55:30 [frame:3] Frames last 0.04s = 1764 audio samples = 1 video samples = 1764 ticks.
2022/07/07 14:55:30 [sandbox:3] Sandboxing disabled
2022/07/07 14:55:30 [video.converter:3] Using preferred video converter: ffmpeg.
2022/07/07 14:55:30 [audio.converter:3] Using samplerate converter: ffmpeg.
2022/07/07 14:55:30 [clock:4] Currently 1 clock(s) allocated.
2022/07/07 14:55:30 [clock.main:4] Starting 1 source(s)...
2022/07/07 14:55:30 [source:4] Source output.icecast_0 gets up with content kind: {audio=pcm(stereo),video=none,midi=none}.
2022/07/07 14:55:30 [auto_dj:4] Content type is {audio=pcm(stereo),video=none,midi=none}.
2022/07/07 14:55:30 [source:4] Source single_0 gets up with content kind: {audio=pcm(stereo),video=none,midi=none}.
2022/07/07 14:55:30 [single_0:3] /root/media/raj3en_ya_hawa.mp3 is static, resolving once for all...
2022/07/07 14:55:30 [decoder.ogg:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.ogg:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder.mp4:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.mp4:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder.aac:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.aac:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder.flac:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.flac:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder.aiff:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.aiff:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder.wav:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.wav:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder:4] Available decoders: FFMPEG (priority: 10), MAD (priority: 1)
2022/07/07 14:55:30 [decoder.ffmpeg:4] ffmpeg recognizes /root/media/raj3en_ya_hawa.mp3 as: audio: {codec: mp3, 44100Hz, 2 channel(s)} and content-type: {audio=pcm(stereo),video=none,midi=none}.
2022/07/07 14:55:30 [decoder:4] Selected decoder FFMPEG for file "/root/media/raj3en_ya_hawa.mp3" with expected kind {audio=pcm(stereo),video=none,midi=none} and detected content {audio=pcm(stereo),video=none,midi=none}
2022/07/07 14:55:30 [metadata.flac:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [metadata.flac:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [metadata.mp4:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [metadata.mp4:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [decoder.ogg:4] Unsupported file extension for "/root/media/raj3en_ya_hawa.mp3"!
2022/07/07 14:55:30 [decoder.ogg:4] Unsupported MIME type for "/root/media/raj3en_ya_hawa.mp3": audio/mpeg!
2022/07/07 14:55:30 [threads:4] Created thread "clock_main" (1 total).
2022/07/07 14:55:30 [clock:4] Main phase starts.
2022/07/07 14:55:30 [threads:4] Created thread "generic queue #1" (1 total).
2022/07/07 14:55:30 [threads:4] Created thread "generic queue #2" (2 total).
2022/07/07 14:55:30 [threads:4] Created thread "non-blocking queue #1" (3 total).
2022/07/07 14:55:30 [threads:4] Created thread "non-blocking queue #2" (4 total).
2022/07/07 14:55:30 [video.add_text:3] Using ffmpeg implementation
2022/07/07 14:55:30 [clock.main:3] Streaming loop starts in auto-sync mode
2022/07/07 14:55:30 [clock.main:3] Delegating synchronisation to CPU clock
2022/07/07 14:55:30 [single_0:3] Prepared "/root/media/raj3en_ya_hawa.mp3" (RID 0).
2022/07/07 14:55:30 [auto_dj:3] Connecting mount stream for source@127.0.0.1...
2022/07/07 14:55:30 [stderr:3] [mp3float @ 0x7ffb7c021b40] Could not update timestamps for skipped samples.
2022/07/07 14:55:30 [auto_dj:3] Connection setup was successful.
2022/07/07 15:01:18 [stderr:3] [mp3float @ 0x7ffb7c021b40] Could not update timestamps for discarded samples.
2022/07/07 15:01:18 [decoder:4] Decoding "/root/media/raj3en_ya_hawa.mp3" ended: Ffmpeg_decoder.End_of_file.
2022/07/07 15:01:18 [decoder:4] Raised at Ffmpeg_decoder.mk_decoder.(fun).f in file "decoder/ffmpeg_decoder.ml", line 691, characters 12-29
2022/07/07 15:01:18 [decoder:4] Called from Decoder.mk_decoder.fill in file "decoder/decoder.ml", line 500, characters 10-31
2022/07/07 15:01:18 [decoder:4]
2022/07/07 15:01:19 [single_0:4] Finished with "/root/media/raj3en_ya_hawa.mp3".
2022/07/07 15:01:19 [single_0:3] Prepared "/root/media/raj3en_ya_hawa.mp3" (RID 0).
2022/07/07 15:01:19 [stderr:3] [mp3float @ 0x7ffb7c061100] Could not update timestamps for skipped samples.

Regards

toots commented 2 years ago

Thanks for this detailed bug report. Will have a look shortly

caf2022 commented 2 years ago

I have the same issue on https://github.com/savonet/liquidsoap/discussions/2439

The problem is that the map.metadata running before icecast/shoutcast connection then not send the first current song, only the first. Maybe if put a condition that sleep the map.metadata some seconds on first run or wait the streaming connection before running.

toots commented 2 years ago

Thanks for reporting this issue. I believe that it should be fixed now. We will proceed with a release of a 2.0.7 bugfix release and the first 2.1.0 release very shortly. Both releases should include the fix.

wezo3 commented 2 years ago

@toots Thank you for the fix and your response but half of issue fixed only its fixed for Liquidsoap restart or start but if we restart icecast or shourcast server without restart Liquidsoap process, the issue still not fixed must wait to start second track

I think this is because Liquidsoap send metadata one time only when start track so when restart icecast process not send metadata again to output until Liquidsoap prepare next track to start to collect and send new metadata again can you set option or auto send metadata every few seconds with encoding output ? so when stop and restart icecast service the metadata send again instead of wait to second track

Regards

toots commented 2 years ago

Hi,

This can be implemented in your script. I would do something like that:

last_metadata = ref([])

source = ...

source = source.on_metadata(source, fun (m) -> last_metadata := m)

source = insert_metadata(source)

insert_metadata = source.insert_metadata

icecast_error = ref(false)

def on_error(_) =
  icecast_error := true
  3.
end

def on_connect() =
  if !icecast_error then
    if !last_metadata <> [] then
      insert_metadata(!last_metadata)
    end
    icecast_error := false
  end
end

output.icecast(on_error=on_error, on_connect=on_connect, ..., source)

This should re-inject the latest metadata each time your output.icecast is reconnecting after encountering an error.

(code not tested!)

wezo3 commented 2 years ago

@toots Thank you, excuse me I'm not aware good with this code so when I use it appear Error 2: Parse error

can please help to put example for my code to success add auto insert metadata ?

this is my code :

input = single("/root/media/raj3en_ya_hawa.mp3")
output.icecast( %mp3.cbr(stereo=true,stereo_mode="default",samplerate=44100,bitrate=320,id3v2=true),
name="auto dj",
public=true,
description="test 11",
url="domain.com",
mount="stream",
host="127.0.0.1",
port=8000,
password="passwordhere111",
genre="music1",
fallible=true, input)

Sorry to bother you and thank you Regards

wezo3 commented 2 years ago

can you please help with this @toots about your code appear error

    if !last_metadata <> [] then

Error 2: Parse error

can you please show hint in my code above ? Thanks