i provide streaming audio and video solutions and hosting to a small community of like minded individuals. a single shoutcast server or more advanced broadcasting solutions utilizing custom scripting and tools for seamless automation and instant syndication of your media (live or archived) to sites such as youtube, justin.tv, twitch.tv, ustream.tv, soundcloud, amazon, and more.

connects to a remote shoutcast server and transcodes to aac and mp3 and rebroadcasts to multiple shoutcast servers
shoutast based sources (djs) connect, switching from the remote source to the live source immediately, and back on disconnect
if the remote source fails, play a local file

put the following code into a file.liq and run

#!/usr/bin/liquidsoap

# set full path to logfile
set("log.file.path","/var/log/liquidsoap/radiostation.log")

# enable daemon mode
set("init.daemon",true)

# change to run under a custom user/group
set("init.daemon.change_user",true)
set("init.daemon.change_user.group","username")
set("init.daemon.change_user.user","groupname")

# do not create a pid file
set("init.daemon.pidfile",false)

# ip to listen on for djs and sources
set("harbor.bind_addr","127.0.0.1")

# remote source to be transcoded
url = "http://www.remotehost.com:8000"
relay = mksafe(input.http(url))

# port and pass for djs
live = input.harbor("/",port=8000,password="djpassword")

# local file
emergency = single("/path/to/some/lastresort.mp3")

# fallback function
radio = fallback(track_sensitive=false,[live,relay,emergency])

# output to shoutcast servers
output.shoutcast(%mp3(bitrate=256,samplerate=44100,stereo=true),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8000,password = "changeme",radio)
output.shoutcast(%mp3(bitrate=128,samplerate=44100,stereo=true),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8010,password = "changeme",radio)
output.shoutcast(%mp3(bitrate=64,samplerate=44100,stereo=true),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8020,password = "changeme",radio)
output.shoutcast(%mp3(bitrate=24,samplerate=22050,stereo=false),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8030,password = "changeme",radio)
output.shoutcast(%aac(bitrate=256),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8000,password = "changeme",radio)
output.shoutcast(%aac(bitrate=128),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8010,password = "changeme",radio)
output.shoutcast(%aac(bitrate=64),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8020,password = "changeme",radio)
output.shoutcast(%aac(bitrate=24),name="Radio Station",genre="Genre",host="127.0.0.1",port = 8030,password = "changeme",radio)

php jquery-mobile podcast parser

Use php to curl an rss/xml url and create a filterable, formatted list view for jquery-mobile

requires
php-curl
simple-xml

features
1. unlimited items! (does NOT proxy via google)
2. displays: pubdate, itunes duration, image, title, subtitle, size (MB)
3. audio icons for audio, video icons for videos

usage
1. edit the url to your rss/xml podcast feed
2. open in browser or include

demo
http://www.dlnetworks.net/php-jqm-podcast

download
https://github.com/dlnetworks/php-jquery-mobile-podcast

all web servers log requests to a file. each request is a single line in the logfile that looks something like this

127.0.0.1 - - [04/Jun/2014:21:00:48 -0700] "GET /ARCHIVE_-_0000-00-00_-_Show_Name_With_DJ_Name_From_Location.mp3 HTTP/1.1" 200 140398275 "-" "iTunes/11.2.1 (Macintosh; OS X 10.9.3) AppleWebKit/537.75.14"

there is a log entry for every whole or partial content request. every time you visit a website, for every image you see, for every js, css, etc file that loads is an entry. on busy sites this log file can become huge. the log file i used for this demonstration has 22,577 lines. each line (see above) can tell you a few things:

the ip address of the person making the request
time stamp
request type and request
http response code
bytes transferred
user agent

and now, with a wonderful tool called logstalgia combined with ffmpeg and some command line-fu

cat /var/log/apache2/podcast.access.log | logstalgia -1920x1080 -g Archives,ARCHIVE,99 --paddle-mode pid --update-rate 1 --output-framerate 60 --output-ppm-stream - - | ffmpeg -f image2pipe -r 60 -c:v ppm -s 1920x1080 -pix_fmt yuv420p -i - -crf 1 -c:v h264 -pix_fmt yuv420p -f mp4 outfile.mp4

and if you want real time…

tail -F -q /var/log/apache2/podcast.access.log | logstalgia -1920x1080 -g Archives,ARCHIVE,99 --paddle-mode pid --update-rate 1 --output-framerate 60 --output-ppm-stream - - | ffmpeg -f image2pipe -r 60 -c:v ppm -s 1920x1080 -pix_fmt yuv420p -i - -crf 1 -c:v h264 -pix_fmt yuv420p -f flv rtmp://videoservice.com/live/secretkey

and.. the timescale is non-linear! (because i like to fiddle)

Date | Hits | Bandwidth
6/04 | 20,034 | 2365.35 GB (2.3TB)
6/05 | 12,702 | 1528.78 GB (1.5TB)

T: 2 | 32,736 | 3894.13 GB (3.8TB)

and heres one using logs from a more well established instance of apache.

the goal:

use ffmpeg to stream audio from shoutcast and a video loop to ustream.tv, justin.tv, twitch.tv, youtube, wowza, flash media server, etc

because ffmpeg -loop 1 seems to only support images, export your loop video file as an image sequence (jpeg,png,etc)

so lets get started. in this example lets output to wowza (mpegts)

ffmpeg -i http://shoutcast.domain.com:port -re -loop 1 -pattern_type glob -i 'live/*.jpg' -c:v libx264 -b:v 3000k -pix_fmt yuvj420p -bsf h264_mp4toannexb -profile:v main -level 41 -g 20 -c:a libfdk_aac -b:a 192k -f mpegts udp://IP:10000?pkt_size=1316

breakitdown

-re will read the image sequence at native/default fps
-loop 1 loops a single image or image sequence
-pattern_type glob allows usage of *
-i '/path/to/loop00*.jpg' path to your image(s) sequence
-i http://shoutcast.domain.com:port host and port of shoutcast server
-f mpegts use mpegts for output
udp://IP:10000?pkt_size=1316 stream to udp port

console output

ffmpeg version 2.1.3 Copyright (c) 2000-2013 the FFmpeg developers
built on Jan 21 2014 17:05:51 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5)
configuration: --prefix=/usr/local --extra-ldflags=-L/usr/local/lib --enable-openssl --enable-openal --enable-libxvid --enable-libx264 --enable-libwavpack --enable-libvorbis --enable-libvo-aacenc --enable-libtheora --enable-libssh --enable-librtmp --enable-libopenjpeg --enable-libopencv --enable-libmp3lame --enable-avisynth --enable-libaacplus --enable-libbluray --enable-libfaac --enable-libfdk-aac --enable-avresample --enable-gray --enable-nonfree --enable-version3 --enable-gpl
libavutil 52. 48.101 / 52. 48.101
libavcodec 55. 39.101 / 55. 39.101
libavformat 55. 19.104 / 55. 19.104
libavdevice 55. 5.100 / 55. 5.100
libavfilter 3. 90.100 / 3. 90.100
libavresample 1. 1. 0 / 1. 1. 0
libswscale 2. 5.101 / 2. 5.101
libswresample 0. 17.104 / 0. 17.104
libpostproc 52. 3.100 / 52. 3.100
Input #0, mp3, from 'http://relay1.dubstep.fm:80':
Duration: N/A, start: 0.000000, bitrate: 192 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 192 kb/s
Input #1, image2, from 'live/*.jpg':
Duration: 00:00:24.00, start: 0.000000, bitrate: N/A
Stream #1:0: Video: mjpeg, yuvj420p(pc), 1280x720 [SAR 72:72 DAR 16:9], 25 fps, 25 tbr, 25 tbn, 25 tbc
[libx264 @ 0xa0b2960] using SAR=1/1
[libx264 @ 0xa0b2960] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 @ 0xa0b2960] profile Main, level 4.1
Output #0, mpegts, to 'udp://IP:10000?pkt_size=1316':
Metadata:
encoder : Lavf55.19.104
Stream #0:0: Video: h264 (libx264), yuvj420p, 1280x720 [SAR 1:1 DAR 16:9], q=-1--1, 3000 kb/s, 90k tbn, 25 tbc
Stream #0:1: Audio: aac (libfdk_aac), 44100 Hz, stereo, s16, 192 kb/s
Stream mapping:
Stream #1:0 -> #0:0 (mjpeg -> libx264)
Stream #0:0 -> #0:1 (mp3 -> libfdk_aac)
Press [q] to stop, [?] for help
frame= 7482 fps= 25 q=12.0 size= 127133kB time=00:05:10.12 bitrate=3358.2kbits/s

to stream to ustream.tv just change to -f flv rtmp://ustream.tv/url/key and so on for the other services.

you may use any encoder you like as long as its supported by ustream.tv, justin.tv, twitch.tv, youtube, wowza, flash media server, etc

and for a little fun

when -loop 1 is set ffmpeg seems to read the file on every loop cycle, which means once ffmpeg is running and looping your image sequence, you can edit any of the individual image files and ffmpeg will stream the updated frames/images on the next loop cycle. this means you can edit/change individual frames in real time. (fight club lol)

if you want to use a single image file, for example -loop 1 -i image.png, you can then open with photoshop and make changes to layers, opacity, etc. just save the file and ffmpeg will stream it out!

note that if your using glob *.jpg for an image sequence, you can only make changes to files that were present at the time ffmpeg was executed. so just dropping another 100 images in the same directory and hoping that *.jpg will pick them up wont work, sorry :/

from what i can tell ffmpeg really hasnt been utilized in this particular way, but is good for radio station owners that want to take advantage of all available delivery methods.

(edit 04.19.14 – i have since bagged the still image, or looping video for something a bit sexier)

http://www.dsfm.tv

cheers =]

DL