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

"Unknown" title appears randomly #1244

Closed namebee closed 4 years ago

namebee commented 4 years ago

I've used liquidsoap for a year now, And it's great so far! But sometimes it likes to switch over to "Unknown" title and it usually stays like that for a long time, Is there a way to prevent this? I'm using liquidsoap 1.3.7.

I tried scanning the logs for issues but all I found were tracks that had "Unknown" in them using grep.

Thank you in advance.

toots commented 4 years ago

Hi! We have some tricks to prevent that. Could you share more details of your script? Thks!

namebee commented 4 years ago

Hello @toots ! My script is just 8 harbor inputs with a fallback that stream to icecast in mp3. Here's a snippet with all names and details removed: https://pastebin.com/raw/zN8wD4ed

toots commented 4 years ago

Ok. Do you know where this metadata comes from? Is that from the live (harbor) source of from the fallback?

namebee commented 4 years ago

I’m not sure where the “Unknown” comes from, I think it appears when there is a very very short connection loss. Normal metadata comes from harbor.

toots commented 4 years ago

Ok. A first approach is to simply filter these out. Something like this:

# Remove ("title","Unknown") metadata
def f(m) =
  def unknown_title(el) = el == ("title","Unknown") end
  list.filter(unknown_title, m)
end

s = map_metadata(update=false, f, s)
namebee commented 4 years ago

Sorry for my lack of understanding and my late response, But how exactly do I use this? Do I just copy past this in and map_metadata does everything for me?

toots commented 4 years ago

No problem! Here's a function that should remove all "Unknown" metadata from a source. You can add it at the very end of your script to make sure it catches all cases:

def remove_unknown(s)
  # Remove (_,"Unknown") metadata
  def f(m) =
    def unknown_meta(el) =
      let (_, m) = el
      m != "Unknown"
    end

    list.filter(unknown_meta, m)
  end

  map_metadata(update=false, f, s)
end
namebee commented 4 years ago

So I just add that function to the end of the .liq file, I don't have to call remove_unknown(source_name) on every source?

toots commented 4 years ago

If it's on the last source before the output it should catch all cases.

namebee commented 4 years ago

I feel so dumb, So should I move all my outputs to the end of the file and add that in the middle? I'm wanting to get this right the first time because I have no testing instance.

toots commented 4 years ago

I would use the function right before your output. Something like that:

def remove_unknown(s)
  # Remove (_,"Unknown") metadata
  def f(m) =
    def unknown_meta(el) =
      let (_, m) = el
      m != "Unknown"
    end

    list.filter(unknown_meta, m)
  end

  map_metadata(update=false, f, s)
end

s = remove_unknown(s)

output(..., s)

Gonna close this as I believe this function should solve your problem. Feel free to follow-up on slack or open a new issue if needed!

namebee commented 4 years ago

I tried using this script, But instead I get a parsing error.

liquidsoap[10212]: Line 15, char 19 before "=": Parse error!

toots commented 4 years ago

Which version of liquidsoap are you using?

namebee commented 4 years ago

I'm using liquidsoap 1.3.7 as I'm not sure I can use 1.4 on Centos 7.

toots commented 4 years ago

Ha makes sense. The let (x, y) = .. syntax was only introduced in 1.4.x. Updated version:

def remove_unknown(s)
  # Remove (_,"Unknown") metadata
  def f(m) =
    def unknown_meta(el) =
      snd(m) != "Unknown"
    end

    list.filter(unknown_meta, m)
  end

  map_metadata(update=false, f, s)
end
namebee commented 4 years ago

Sorry if this is all my fault, But I get a new error now while using that function like you did above.

liquidsoap[16705]: At line 18, char 32: liquidsoap[16705]: this value has type liquidsoap[16705]: (_*_) (inferred at line 15, char 12) liquidsoap[16705]: but it should be a subtype of liquidsoap[16705]: [_]

I'm putting "s" as a parameter at the end of a icecast output.

toots commented 4 years ago

Ny bad, there was a typo in my code:

def remove_unknown(s)
  # Remove (_,"Unknown") metadata
  def f(m) =
    def unknown_meta(el) =
      snd(el) != "Unknown"
    end

    list.filter(unknown_meta, m)
  end

  map_metadata(update=false, f, s)
end
namebee commented 4 years ago

liquidsoap[2929]: At line 24, char 21: the variable s used here has not been previously

def remove_unknown(s)
  # Remove (_,"Unknown") metadata
  def f(m) =
    def unknown_meta(el) =
      snd(el) != "Unknown"
    end

    list.filter(unknown_meta, m)
  end

  map_metadata(update=false, f, s)
end

s = remove_unknown(s)

I'm not sure what the problem is this time, This was literally what you told me to do. I put the s at the end of an icecast output. Line 24 points to s = remove_unknown(s)

Like so:

redacted_live = audio_to_stereo(input.harbor("redacted",port=8694,password="redacted"))
redacted_full = fallback(track_sensitive=false, [redacted_live,radio])
output.icecast (%mp3.cbr(bitrate=192, samplerate=44100, stereo=true, internal_quality=0, id3v2=true),
                redacted_full, mount="redacted", host="redacted",
                port=8690, password="redacted", fallible=true, s)
namebee commented 4 years ago

Hello @toots, Is there any way I can resolve this?

ivellios1988 commented 3 years ago

I know this is an old issue but maybe this will help someone. 's' is the variable that, so to say, 'defines' the signal that is sent to your output. Inspect your Liquidsoap configuration file to determine the name of the variable 'defining' your signal and replace 's' with it. For example, I use AzuraCast and, by default, it uses a variable called 'radio'. So I used the code from your last comment, replacing 's' with 'radio' - and everything's working fine.

ivellios1988 commented 3 years ago

Well, it looks like I'm the one in need for help now :D I'm currently fighting with similar issue on my AzuraCast installation. I care a lot about ID3 tags in my MP3 files. So after uploading them to my server I tagged them all so that they have at least the title and the artist's name. And now some kind of Russian roulette begins because in most cases the title and artist are correctly displayed by IceCast, but in case of some MP3s the title gets reverted to 'Unknown' and this 'Unknown' stays in the title bar until the next track is played. I'm not sure exactly why this happens because the same track can produce 'Unknown' and when it's played again another time, it's title and artist name are displayed correctly.

What's more, every time when this 'Unknown' thing happens, the correct title of the audio file currently played is displayed as 'next song'.

I tried applying the remove_unknown function provided by @toots (version for Liquidsoap 1.3.7, haven't tried the one for 1.4.0 yet) and it works perfectly until a live DJ connects. Then yet another Russian roulette begins, because either the title is shown correctly or it gets reverted to 'Unknown' again. So far I figured out that it largely depends on the length of the title sent by the live DJ's software and the presence or lack of the "-" symbol. "Artist - Title" combination is short - no problem, the title is displayed correctly and everything is fine; longer metadata - BOOM! 'Unknown' appears.