Difference between revisions of "User:Mjb/Winamp & SHOUTcast"
(→Winamp playlist regeneration on Windows) |
(+Liquidsoap) |
||
Line 36: | Line 36: | ||
I don't remember if I tried any of these. The idea, though, was that if I could send the data to a file, the file could actually be a named pipe into icecast or something. However it didn't occur to me that I'd probably lose the protocol data (stream info and song titles). So it was starting to look like the only real option was going to be [http://www.oddsock.org/tools/streamTranscoder/ streamTranscoder], last updated in 2004. | I don't remember if I tried any of these. The idea, though, was that if I could send the data to a file, the file could actually be a named pipe into icecast or something. However it didn't occur to me that I'd probably lose the protocol data (stream info and song titles). So it was starting to look like the only real option was going to be [http://www.oddsock.org/tools/streamTranscoder/ streamTranscoder], last updated in 2004. | ||
+ | |||
+ | ==Liquidsoap== | ||
+ | |||
+ | In December 2015, I began using the [[http://liquidsoap.fm/ Liquidsoap]] command-line scripting language to generate crossfaded AAC streams for my SHOUTcast and Icecast servers. It works a little better with Icecast. | ||
+ | |||
+ | I installed the standard Windows build, modified the test.liq script as shown below (but with working hosts, ports, and passwords), and ran "liquidsoap mytest.liq" on the command line. | ||
+ | |||
+ | <pre># configure logging | ||
+ | set("log.stdout",true) | ||
+ | set("log.file",false) | ||
+ | set("log.level",4) | ||
+ | |||
+ | # allow sending commands to server while it's running | ||
+ | # sample commands: playlist(dot)m3u8.reload | ||
+ | set("server.telnet",true) | ||
+ | set("server.telnet.port", 2425) | ||
+ | |||
+ | # create a source from a playlist | ||
+ | s = playlist(mime_type="application/x-mpegURL","/docs/private/Desktop/playlist.m3u8") | ||
+ | |||
+ | # make the source go to next track when raw volume dips below -78 dBFS for more than 2s | ||
+ | s = skip_blank(threshold=-78.,max_blank=2.,s) | ||
+ | |||
+ | # make the source adjust output volume based on ReplayGain Track Gain tag | ||
+ | s = amplify(1.,override="REPLAYGAIN_TRACK_GAIN",s) | ||
+ | |||
+ | # smart_crossfade is difficult to tune, so I'm not using this yet. | ||
+ | # look into conservative=true and replacing fade_out with fade_final. | ||
+ | # s = smart_crossfade(start_next=20.,fade_in=10.,width=20.,fade_out=20.,margin=0.,s) | ||
+ | |||
+ | # simple crossfade is easier to use, but all tracks fade the same way | ||
+ | # start_next = crossfade duration, i.e. how far before end of current track to start playing next track | ||
+ | # fade_in = fade-in duration of next track | ||
+ | # fade_out = fade-out duration of current track | ||
+ | s = crossfade(start_next=15.,fade_in=10.,fade_out=15.,s) | ||
+ | |||
+ | # Output to the local soundcard | ||
+ | output.ao(fallible=true,s) | ||
+ | |||
+ | # Output raw 128 kbps AAC-LC to a file | ||
+ | #output.file(fallible=true, %fdkaac(channels=2, samplerate=44100, bitrate=128, afterburner=false, aot="mpeg2_aac_lc", transmux="adts", sbr_mode=false), "out.aac", s) | ||
+ | |||
+ | # Output 128 kbps AAC-LC to a remote Icecast server | ||
+ | output.icecast(fallible=true, %fdkaac(channels=2, samplerate=44100, bitrate=128, afterburner=false, aot="mpeg2_aac_lc", transmux="adts", sbr_mode=false), host="foo.example.org", port=8000, password="hackme", mount="/", encoding="UTF-8", description="a description goes here", url="https://www.example.org/", public=false, s) | ||
+ | |||
+ | # Output 256 kbps AAC-LC to a local SHOUTcast server | ||
+ | output.icecast(fallible=true, %fdkaac(channels=2, samplerate=44100, bitrate=256, afterburner=false, aot="mpeg2_aac_lc", transmux="adts", sbr_mode=false), protocol="icy", icy_metadata="true", host="localhost", port=8000, password="hackme", mount="stream", encoding="UTF-8", description="a description goes here", url="https://www.example.org/", public=false, s) | ||
+ | </pre> |
Revision as of 00:51, 8 December 2015
Winamp playlist regeneration on Windows
Every day, I want to:
- Regenerate a UTF-8-encoded playlist, picking up any changes made on my file system
- Load the new playlist in Winamp
I used to have a clever Python script for this purpose, but installing Python on Windows is an awfully steep prequisite. As it turns out, a single Windows command-shell command does the trick. This all goes on one line:
cmd.exe /C "chcp 65001 && dir Z:\music /b /s | findstr /e /l ".mp3 .flac .m4a .wav .wma .ogg .mp2" | findstr /e /l /v ".lnk" > playlist.m3u8" && start /b playlist.m3u8
Here's an explanation:
&&
= if the previous command completed without error, do what comes next.|
= pipe the text output of the previous command as input to the next.>
… = put the output of the previous command into the designated file.cmd.exe /C "
…"
= open a command shell window and run the quoted command(s).chcp 65001
= set the active code page to UTF-8dir
…/b /s
= recursively list the files in the given folder(s), only listing their full paths.findstr /e /l "
…"
= output only lines ending with any of these literal strings.findstr /e /l /v "
…"
= output lines not ending with any of these literal strings.start /b
… = open the designated file as a background process (no window).
To get it to run every day, you need to add it to the Task Scheduler, where you also tell it what directory to run from (i.e. where you want the playlist file to go, if you didn't specify a path in the command line). You access the Task Scheduler GUI through the Management Console or with a command-line command (schtasks), the syntax of which is too painful to deal with. Just use the GUI.
SHOUTcast stream transcoding
In 2008, I was looking into offering a low-bitrate MP3 version of an audio stream by connecting to it as a client, transcoding it, and feeding it to another server.
I didn't get very far in my research, but did find several options for grabbing a stream to a file on Unix:
mpg123 -b 4096 -s streamURL > out.mp3 gnetcat -l -p 8081 streamIP streamPort | lame --mp3input -b 64 - out.mp3 mpg123 -b 4096 -s streamURL | lame --mp3input -b 64 - out.mp3
And then there was also fIcy: an icecast/shoutcast stream grabber suite.
I don't remember if I tried any of these. The idea, though, was that if I could send the data to a file, the file could actually be a named pipe into icecast or something. However it didn't occur to me that I'd probably lose the protocol data (stream info and song titles). So it was starting to look like the only real option was going to be streamTranscoder, last updated in 2004.
Liquidsoap
In December 2015, I began using the [Liquidsoap] command-line scripting language to generate crossfaded AAC streams for my SHOUTcast and Icecast servers. It works a little better with Icecast.
I installed the standard Windows build, modified the test.liq script as shown below (but with working hosts, ports, and passwords), and ran "liquidsoap mytest.liq" on the command line.
# configure logging set("log.stdout",true) set("log.file",false) set("log.level",4) # allow sending commands to server while it's running # sample commands: playlist(dot)m3u8.reload set("server.telnet",true) set("server.telnet.port", 2425) # create a source from a playlist s = playlist(mime_type="application/x-mpegURL","/docs/private/Desktop/playlist.m3u8") # make the source go to next track when raw volume dips below -78 dBFS for more than 2s s = skip_blank(threshold=-78.,max_blank=2.,s) # make the source adjust output volume based on ReplayGain Track Gain tag s = amplify(1.,override="REPLAYGAIN_TRACK_GAIN",s) # smart_crossfade is difficult to tune, so I'm not using this yet. # look into conservative=true and replacing fade_out with fade_final. # s = smart_crossfade(start_next=20.,fade_in=10.,width=20.,fade_out=20.,margin=0.,s) # simple crossfade is easier to use, but all tracks fade the same way # start_next = crossfade duration, i.e. how far before end of current track to start playing next track # fade_in = fade-in duration of next track # fade_out = fade-out duration of current track s = crossfade(start_next=15.,fade_in=10.,fade_out=15.,s) # Output to the local soundcard output.ao(fallible=true,s) # Output raw 128 kbps AAC-LC to a file #output.file(fallible=true, %fdkaac(channels=2, samplerate=44100, bitrate=128, afterburner=false, aot="mpeg2_aac_lc", transmux="adts", sbr_mode=false), "out.aac", s) # Output 128 kbps AAC-LC to a remote Icecast server output.icecast(fallible=true, %fdkaac(channels=2, samplerate=44100, bitrate=128, afterburner=false, aot="mpeg2_aac_lc", transmux="adts", sbr_mode=false), host="foo.example.org", port=8000, password="hackme", mount="/", encoding="UTF-8", description="a description goes here", url="https://www.example.org/", public=false, s) # Output 256 kbps AAC-LC to a local SHOUTcast server output.icecast(fallible=true, %fdkaac(channels=2, samplerate=44100, bitrate=256, afterburner=false, aot="mpeg2_aac_lc", transmux="adts", sbr_mode=false), protocol="icy", icy_metadata="true", host="localhost", port=8000, password="hackme", mount="stream", encoding="UTF-8", description="a description goes here", url="https://www.example.org/", public=false, s)