#141: "Too Many Open Files" liquidsoap does not release the mp3 it has played?
-------------------------+--------------------------------------------------
Reporter: ~ok| | Owner: admin
Type: Bugs | Status: new
Priority: 4 | Milestone: 0.3.7
Component: Liquidsoap | Version: 0.3.6+svn
Resolution: | Keywords:
Mac: 0 | Linux: 0
Netbsd: 1 | Other: 0
Freebsd: 0 |
-------------------------+--------------------------------------------------
Comment (by ~ok|):
just in case here's my current testing radio.liq:
{{{
#!/home/demo01/radio/liquidsoap/bin/liquidsoap
set("log.level",7)
set("log.file.path", "/var/log/liquidsoaplog")
set("decoding.buffer_length",20.)
set("scheduler.log",true)
#set("init.daemon",true)
set("init.daemon.pidfile.path",
"/home/demo01/radio/liquidsoap/var/run/liquidsoap.pid")
#set("server.socket",true)
set("server.socket.path","/tmp/liquidaudio.sock")
set("server.telnet",true)
set("log.stdout", false)
set("scheduler.event_queues",3)
# === Settings ===
icecast_password = "XXX"
icecast_host = "192.168.1.2"
icecast_port = 8000
lastfm_user = "demo01Robot"
lastfm_password="XXX"
radio_descr = "Demo01"
radio_url = "http://demo01.intern.local/"
#Path to Radiopilote env.init.php
radiopilote_conf = "/home/demo01/radio/html/init"
# Script prefixing
scripts = "/home/demo01/radio/radiopilote/scripts/"
# A file for playing during failures
interlude =
playlist.safe("/home/demo01/radio/liquidsoap/var/BACKUP/BACKUP.pls")
# === Main script ===
output.icecast = output.icecast.mp3(
restart=true,
description=radio_descr,
url=radio_url
)
out = output.icecast(
host=icecast_host,
port=icecast_port,
password=icecast_password,
stereo=true,
samplerate=44100,
bitrate=128
)
def fallback.transition(previous,next)
add([fade.in(next),fade.final(duration=5.,previous)])
end
def sky(s)
# 3-band crossover
low = filter.iir.eq.low(frequency = 168.)
mh = filter.iir.eq.high(frequency = 100.)
mid = filter.iir.eq.low(frequency = 1800.)
high = filter.iir.eq.high(frequency = 1366.)
# Add back
add(normalize = false,
[ compress(attack = 100., release = 200., threshold = -20.,
ratio = 3., gain = 2., knee = 0.3,
low(s)),
compress(attack = 100., release = 200., threshold = -20.,
ratio = 3., gain = 2., knee = 0.3,
mid(mh(s))),
compress(attack = 100., release = 200., threshold = -20.,
ratio = 3., gain = 2., knee = 0.3,
high(s))
])
end
def rewrite_metadata(l,~insert_missing=true,s)
def map(m)
def apply(x)
label = fst(x)
value = snd(x)
(label,value % m)
end
list.map(apply,l)
end
map_metadata(map,insert_missing=insert_missing,s)
end
def smart_crossfade (~start_next=5.,~fade_in=3.,~fade_out=3.,
~width=2.,~conservative=false,s)
high = -20.
medium = -32.
margin = 4.
fade.out = fade.out(type="sin",duration=fade_out)
fade.in = fade.in(type="sin",duration=fade_in)
add = fun (a,b) -> add(normalize=false,[b,a])
log = log(label="smart_crossfade")
def transition(a,b,ma,mb,sa,sb)
list.iter(fun(x)-> log(level=4,"Before: #{x}"),ma)
list.iter(fun(x)-> log(level=4,"After : #{x}"),mb)
if
# If A and B and not too loud and close, fully cross-fade them.
a <= medium and b <= medium and abs(a - b) <= margin
then
log("Transition: crossed, fade-in, fade-out.")
add(fade.out(sa),fade.in(sb))
elsif
# If B is significantly louder than A, only fade-out A.
# We don't want to fade almost silent things, ask for >medium.
b >= a + margin and a >= medium and b <= high
then
log("Transition: crossed, fade-out.")
add(fade.out(sa),sb)
elsif
# Do not fade if it's already very low.
b >= a + margin and a <= medium and b <= high
then
log("Transition: crossed, no fade-out.")
add(sa,sb)
elsif
# Opposite as the previous one.
a >= b + margin and b >= medium and a <= high
then
log("Transition: crossed, fade-in.")
add(sa,fade.in(sb))
# What to do with a loud end and a quiet beginning ?
# A good idea is to use a jingle to separate the two tracks,
# but that's another story.
else
# Otherwise, A and B are just too loud to overlap nicely,
# or the difference between them is too large and overlapping would
# completely mask one of them.
log("No transition: just sequencing.")
sequence([sa, sb])
end
end
smart_cross(width=width, duration=start_next, conservative=conservative,
transition,s)
end
# === Channels ===
# Lastfm submission
def lastfm (m) =
# Only submit songs of type "chansons" (got type using annotate..)
if (m["type"] == "songs") then
canal = m["canal"]
lastfm.submit(user=lastfm_user,password=lastfm_password,m)
end
end
# To create a channel from a basic source, add:
# - a new-track notification for radiopilote
# - metadata rewriting
# - the live shows
# - the failsafe 'interlude' source to channels
# - blank detection
# - gentle compression
def mklive(source)
# This script updates a lastfm account for each channel...
# source = on_metadata( fun (meta) ->
# system("/usr/pkg/bin/lastfm_submission
"^quote(lastfm_conf)^" "
# ^quote(meta["canal"])^ " "
# ^quote(meta["title"])^" "
# ^quote(meta["artist"])^" "
# ^quote(meta["album"])^" "
# ^quote(meta["length"])^" "
# ^quote(meta["type"])^" &"), source)
# Add lastfm submission
source = on_metadata(lastfm,source)
# This scripts tells us that this file has been played
source = on_metadata(
fun (meta) ->
system(
scripts^"radiopilote-feedback
"^quote(radiopilote_conf)^" "^quote(meta["canal"])^"
"^quote(meta["file_id"])
), source)
# Some metadata rewriting, new values are provided by the anotate plugin
source = rewrite_metadata(
[("artist",'$(if $(display_artist),"$(display_artist)","$(artist)")'),
("comment",""),
("title", '$(if $(display_title),"$(display_title)","$(title)")'),
("album", '$(if $(display_album),"$(display_album)","$(album)")')],
fallback(track_sensitive=false, [source, interlude])
)
# Compress the sound
# normalize(compress(threshold=-15.,ratio=2.,source))
normalize(sky(source), gain_min=-9., gain_max=12.)
end
# === Basic sources ===
# Create a radiopilote-driven source
def channel_radiopilote(~skip=true,name)
log("Creating channel #[name]")
# Request function
def request () =
log("Request for #{name}")
req_str = scripts ^ "radiopilote-getnext " ^ quote(radiopilote_conf) ^
" " ^ quote(name);
log(req_str)
req_output = get_process_output(req_str)
log(req_output)
request.create(audio=true,
# get_process_output(scripts ^ "radiopilote-getnext " ^
quote(radiopilote_conf) ^ " " ^ quote(name)) )
req_output)
end
# Basic source
source = request.dynamic(
id="dyn_"^name,request)
# Only skip some channels
if skip then
source = skip_blank(source, length=2., threshold=-40.)
end
# Add smart crossfading
smart_crossfade(fade_out=0.5, fade_in=0.5, source)
end
# Channels encoded here
main = channel_radiopilote("Main")
# Create a channel using mklive(), encode and output it to icecast.
def mkoutput(mount,source,name)
out(mount=mount,name=name,
mklive(source))
end
# === Outputs ===
# These channels are encoded on this machine
main = mkoutput("main", main, "Demo01 - Main channel")
# Finally the web channel, and its mp3 version
web =
out(
mount="stream",
name=radio_descr^" - "^radio_url,
fallback([main, interlude])
)
}}}
--
Ticket URL: <http://savonet.rastageeks.org/ticket/141#comment:10>
Savonet <http://savonet.rastageeks.org/>
Let's program our stream !
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Savonet-trac mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/savonet-trac