Compare commits
11 Commits
d2d60f43cb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 951b00385a | |||
| 5c65206c34 | |||
| 8f8bb57fd1 | |||
| 7b3f1768d2 | |||
| 528fd7f622 | |||
| 130693884b | |||
| 437d3129e5 | |||
| afbd9a1820 | |||
| 401ca965fc | |||
| 0ad0aa13fb | |||
| df708844f5 |
80
Makefile
Normal file
80
Makefile
Normal file
@ -0,0 +1,80 @@
|
||||
# Makefile for shred.ing
|
||||
|
||||
# make (default, or with: make config)
|
||||
# prompt for settings unless .env file exists
|
||||
# create ~/icecast.xml
|
||||
# make install
|
||||
# backup the live config to ~/icecast.xml
|
||||
# install ~/icecast.xml to /etc/icecast2
|
||||
|
||||
# not currently used for anything
|
||||
## make sure to change these
|
||||
#source_pass := password_to_share_with_casters
|
||||
#relay_pass := password_for_icecast2_relays
|
||||
#admin_user := admin_web_and_api_username
|
||||
#admin_pass := password_for_admin_access
|
||||
## probably want to change this
|
||||
#hostname := shred.ing
|
||||
|
||||
# the "prompt" port can be left blank so
|
||||
# this can be left at default
|
||||
icecast2_port := 8000
|
||||
|
||||
##
|
||||
## More or less internal stuffs
|
||||
##
|
||||
|
||||
ICECAST_CONFIG_TEMPLATE ?= icecast.xml.template
|
||||
|
||||
## generate configuration files for icecast2
|
||||
|
||||
# these targets aren't associated with files
|
||||
.PHONEY: config backup-live-config install foo
|
||||
|
||||
## main "entry point" makefile targets
|
||||
config: icecast.xml .env
|
||||
|
||||
backup-live-config:
|
||||
sudo test -r /etc/icecast2/icecast.xml && sudo cp /etc/icecast2/icecast.xml icecast.xml~~
|
||||
|
||||
install: config backup-live-config
|
||||
sudo cp icecast.xml /etc/icecast2/icecast.xml.new
|
||||
|
||||
# this will prompt to build a .env file when none exists
|
||||
.env:
|
||||
@echo "You will receive a series of prompts to create a .env file."
|
||||
@echo
|
||||
@printf "Enter your icecast hostname (or IP): "
|
||||
@printf "hostname=%s\n" `read i; echo $$i` >.env
|
||||
@printf "Enter the port for your icecast server ($(icecast2_port)): "
|
||||
@printf "icecast2_port=%s\n" "$$( i=`read i; echo $$i`; printf "%s" $$( if test -z "$$i" ; then echo "$(icecast2_port)"; else echo "$$i" ; fi ) )" >>.env
|
||||
@echo "Icecast requires, potentially, several passwords."
|
||||
@echo "Passwords entered now are echoed to the screen."
|
||||
@echo "You can pick bogus values and then edit the .env file."
|
||||
@printf "Enter a source password: "
|
||||
@printf "source_pass=%s\n" `read i; echo $$i` >>.env
|
||||
@printf "Enter a relay password: "
|
||||
@printf "relay_pass=%s\n" `read i; echo $$i` >>.env
|
||||
@printf "Enter an admin password: "
|
||||
@printf "admin_pass=%s\n" `read i; echo $$i` >>.env
|
||||
@echo "Finally, select a username for the admin account:"
|
||||
@printf "Enter the icecast admin username: "
|
||||
@printf "admin_user=%s\n" `read i; echo $$i` >>.env
|
||||
|
||||
# this ensures the template icecast config exists
|
||||
$(ICECAST_CONFIG_TEMPLATE):
|
||||
@printf "The icecast2 configuration file template "'"'"%s"'"'"\n" "$(ICECAST_CONFIG_TEMPLATE)"
|
||||
@printf "is missing or cannot be read.\n"
|
||||
@echo "This can be caused by an incomplete or corrupted checkout or"
|
||||
@echo "an invalid value for the ICECAST_CONFIG_TEMPLATE env variable."
|
||||
false
|
||||
|
||||
|
||||
### given we have a template and a .env, create the icecast config
|
||||
icecast.xml: $(ICECAST_CONFIG_TEMPLATE) .env
|
||||
perl -e 'BEGIN{open my$$FH,q(<),q(.env) or die $$!; for(<$$FH>){ chomp; my($$k,$$v) = split q(=); next unless $$k; $$k =~ s/^\s+|\s+$$//g; next unless $$k; $$v =~ s/^\s+|\s+//g; $$h{lc $$k} = $$v; }}' -pe 's/\@\@([^@]+)\@\@/$$h{lc $$1}/eig;' >icecast.xml <$(ICECAST_CONFIG_TEMPLATE)
|
||||
|
||||
# this seems to work, too!
|
||||
# cat icecast.xml.template | perl -pe 's/\@\@source_pass\@\@/$(source_pass)/ig; s/\@\@relay_pass\@\@/$(relay_pass)/ig; s/\@\@admin_user\@\@/$(admin_user)/ig; s/\@\@admin_pass\@\@/$(admin_pass)/ig; s/\@\@hostname\@\@/$(hostname)/ig; s/\@\@icecast2_port\@\@/$(icecast2_port)/ig;' > icecast.xml
|
||||
# probably, so does this?
|
||||
# cat icecast.xml.template | perl -e 'BEGIN{open my$FH,q(<),q(.env) or die $!; for(<$FH>){ chomp; my($k,$v) = split q(=); next unless $k; $k =~ s/^\s+|\s+$//g; next unless $k; $v =~ s/^\s+|\s+//g; $h{lc $k} = $v; }}' -pe 's/\@\@([^@]+)\@\@/$h{lc $1}/eig;' -e 'END { use Data::Dumper; warn Dumper( \%h ) } ' > foo.xml
|
||||
50
README.md
50
README.md
@ -1,3 +1,51 @@
|
||||
# shred.ing-server
|
||||
|
||||
Stuff to install on a (nominally) Ubuntu 24 host to create (e.g.) shred.ing to create an internet hosted radio station.
|
||||
Stuff to install on a (nominally) Ubuntu 24 host to create (e.g.) shred.ing to create an internet hosted radio station.
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
- [X] fix issue where streams HTML player disconnects after an hour
|
||||
- [X] create fallback streams to support switching casters
|
||||
- [-] build guided installer
|
||||
- [ ] write a tutoral
|
||||
|
||||
# Quick Start
|
||||
|
||||
git clone https://code.bru.st/corwin/shred.ing-server.git
|
||||
apt-get install icecast2
|
||||
make install
|
||||
links localhost:8000
|
||||
|
||||
# ABSTRACT
|
||||
|
||||
Here you will hopefully find everything (aside hardware and content) that you need to get started self-hosting a radio-station. This guide (and the other files in this repository) are focused on creating an internet hosted station but they should work well (albe it, with some adaptions) for creating a station on a private network ("intranet"), too.
|
||||
|
||||
This repository is intended to contain enough information to get started self-hosting an internet radio station. These same instructions should work fairly well for a intranet (private network) based station however some adaptions (such as skipping the "selecting a VPS provider" section) might be advisable. This setup can be a step toward broad-casting over "open" airwaves (however, this generally requires understanding local licesnsing and other applicable governance requirements, etc, which please as you may be inclined ). Additionally, these instructions (the software used here, specifically) should work well use with sophisticaed hardware (lots of analog and/or digital sources, etc.). That said, this is a "getting started" guide as well as instructions for useing the files in this repository. Patches welcome :)
|
||||
|
||||
# DESIGN
|
||||
|
||||
The radio station consists of two parts: the workstation, responsible for broadcasting to the server, and the server responsible for streaming the audio sigal to the devices of whomever may be listening. This repository includes most the configuration, HTML palyer, and other scripting needed for the server however the guild (this file!) contains some tips for working with Mixxx, the recommended broadcaster software.
|
||||
|
||||
## workstation
|
||||
|
||||
Although generally compatable in principle with a wide variety of software, the workstation setup required by this guild consists of a program (Mixxx, GPLv2+). Mixxx is available in the form of pre-compiled binaries for a variety of operating systems.
|
||||
|
||||
## server
|
||||
|
||||
The server is somewhat more complex, but ultimatly relies mainly on two programs (Icecast2, GPLv2; Nginx, BSD-2c): Icecast2 (GPLv2) which receives our mixed signal and streams it to listeners, and nginx (BSD-2c) which is a web-server which will "proxy" the MP3 stream produced by Icecast, not witstanding the underlying (nominally) Ubuntu 24 system software. Since this guide assumes we are building a internet facing server we also cover setting up ufw (a firewall program) and fail2ban (a nusance deturant toolkit), most in the form of explain how to use (and/or adapt!) the same filter rules in this repo.
|
||||
|
||||
## summary
|
||||
|
||||
* This file plus the contents of this repository, along with PC capable running some recent version of Ubuntu (nearly any PC), should be enough to get a simple network radio station online.
|
||||
* This guild is covers the steps to aquire an virtual private server from internet provider and configure it to server your radio station on the internet.
|
||||
* Alternately, these steps should work fairly well starting with old PC you might like to use to create an intranet station.
|
||||
* This guild doesn't give a great deal of coverage to Mixxx (and none to other audio caster software):
|
||||
* Get comfortable with Mixx (or the audio caster software of your choice) before building your own station.
|
||||
* For example, be comforable playing and switching tracks, creating playlists, keying your mic, whatever you plan to do.
|
||||
* This guide recommends Mixxx: install it and mess around!
|
||||
* If you hate Mixxx good search terms could be "audiocaster software send to icecast2".
|
||||
* There are some tips for getting started with Mixxx in the next section and elsewhere below.
|
||||
|
||||
# Materials
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
tail -1 /var/log/icecast2/playlist.log | cut -d \| -f 4 | perl -nle 'printf qq({ "title" : "%s" }\n), $_'
|
||||
65
icecast.nginx-sites-avaialble
Normal file
65
icecast.nginx-sites-avaialble
Normal file
@ -0,0 +1,65 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name shred.ing;
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log;
|
||||
location / {
|
||||
proxy_pass http://localhost:8000/live.mp3;
|
||||
}
|
||||
location ~ play(er)?|html?$ {
|
||||
root /www/shred.ing;
|
||||
try_files $1 /shred.html =404;
|
||||
# kill cache
|
||||
add_header Last-Modified $date_gmt;
|
||||
add_header Cache-Control 'no-store, no-cache';
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
}
|
||||
location ~ js(on)?$ {
|
||||
root /opt/shred.ing/js;
|
||||
try_files $1 /title.json =404;
|
||||
# kill cache
|
||||
add_header Last-Modified $date_gmt;
|
||||
add_header Cache-Control 'no-store, no-cache';
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
server_name shred.ing;
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log;
|
||||
listen [::]:443 ssl; # managed by Certbot
|
||||
listen 443 ssl; # managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/shred.ing/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/shred.ing/privkey.pem; # managed by Certbot
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
||||
location / {
|
||||
proxy_pass http://localhost:8000/live.mp3;
|
||||
}
|
||||
location ~ play(er)?|html?$ {
|
||||
root /www/shred.ing;
|
||||
try_files $1 /shred.html =404;
|
||||
# kill cache
|
||||
add_header Last-Modified $date_gmt;
|
||||
add_header Cache-Control 'no-store, no-cache';
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
}
|
||||
location ~ js(on)?$ {
|
||||
root /opt/shred.ing/js;
|
||||
try_files $1 /title.json =404;
|
||||
# kill cache
|
||||
add_header Last-Modified $date_gmt;
|
||||
add_header Cache-Control 'no-store, no-cache';
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
}
|
||||
}
|
||||
@ -1,55 +1,36 @@
|
||||
<icecast>
|
||||
<!-- location and admin are two arbitrary strings that are e.g. visible
|
||||
on the server info page of the icecast web interface
|
||||
(server_version.xsl). -->
|
||||
<location>Earth</location>
|
||||
<admin>icemaster@localhost</admin>
|
||||
|
||||
<!-- IMPORTANT!
|
||||
Especially for inexperienced users:
|
||||
Start out by ONLY changing all passwords and restarting Icecast.
|
||||
For detailed setup instructions please refer to the documentation.
|
||||
It's also available here: http://icecast.org/docs/
|
||||
-->
|
||||
|
||||
<location>The Island of Misfit Toys</location>
|
||||
<admin>yo@mammy</admin>
|
||||
<limits>
|
||||
<clients>100</clients>
|
||||
<sources>2</sources>
|
||||
<clients>17q000</clients>
|
||||
<sources>17</sources>
|
||||
<queue-size>524288</queue-size>
|
||||
<client-timeout>30</client-timeout>
|
||||
<header-timeout>15</header-timeout>
|
||||
<source-timeout>10</source-timeout>
|
||||
<!-- If enabled, this will provide a burst of data when a client
|
||||
first connects, thereby significantly reducing the startup
|
||||
<source-timeout>17</source-timeout>
|
||||
<!-- If enabled, this will provide a burst of data when a client
|
||||
first connects, thereby significantly reducing the startup
|
||||
time for listeners that do substantial buffering. However,
|
||||
it also significantly increases latency between the source
|
||||
client and listening client. For low-latency setups, you
|
||||
might want to disable this. -->
|
||||
<burst-on-connect>1</burst-on-connect>
|
||||
<!-- <burst-on-connect>1</burst-on-connect> -->
|
||||
<!-- same as burst-on-connect, but this allows for being more
|
||||
specific on how much to burst. Most people won't need to
|
||||
change from the default 64k. Applies to all mountpoints -->
|
||||
<burst-size>65535</burst-size>
|
||||
<!-- <burst-size>65535</burst-size> -->
|
||||
</limits>
|
||||
|
||||
<authentication>
|
||||
<!-- Sources log in with username 'source' -->
|
||||
<source-password>shredsourcepassword</source-password>
|
||||
<source-password>@@Source_Pass@@</source-password>
|
||||
<!-- Relays log in with username 'relay' -->
|
||||
<relay-password>shredrelaypassword</relay-password>
|
||||
|
||||
<relay-password>@@Relay_Pass@@</relay-password>
|
||||
<!-- Admin logs in with the username given below -->
|
||||
<admin-user>admin</admin-user>
|
||||
<admin-password>shredadminpassword</admin-password>
|
||||
<admin-user>@@Admin_User@@</admin-user>
|
||||
<admin-password>@@Admin_Pass@@</admin-password>
|
||||
</authentication>
|
||||
|
||||
<!-- set the mountpoint for a shoutcast source to use, the default if not
|
||||
specified is /stream but you can change it here if an alternative is
|
||||
wanted or an extension is required
|
||||
<shoutcast-mount>/live.nsv</shoutcast-mount>
|
||||
-->
|
||||
|
||||
<!-- Uncomment this if you want directory listings -->
|
||||
<!--
|
||||
<directory>
|
||||
<yp-url-timeout>15</yp-url-timeout>
|
||||
@ -57,41 +38,14 @@
|
||||
</directory>
|
||||
-->
|
||||
|
||||
<!-- This is the hostname other people will use to connect to your server.
|
||||
It affects mainly the urls generated by Icecast for playlists and yp
|
||||
listings. You MUST configure it properly for YP listings to work!
|
||||
-->
|
||||
<hostname>shred.ing</hostname>
|
||||
|
||||
<!-- You may have multiple <listen-socket> elements -->
|
||||
<hostname>@@hostname@@</hostname>
|
||||
<listen-socket>
|
||||
<port>8000</port>
|
||||
<!-- <bind-address>127.0.0.1</bind-address> -->
|
||||
<!-- <shoutcast-mount>/stream</shoutcast-mount> -->
|
||||
<port>@@icecast2_port@@</port>
|
||||
</listen-socket>
|
||||
<!--
|
||||
<listen-socket>
|
||||
<port>8080</port>
|
||||
</listen-socket>
|
||||
-->
|
||||
<!--
|
||||
<listen-socket>
|
||||
<port>8443</port>
|
||||
<ssl>1</ssl>
|
||||
</listen-socket>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Global header settings
|
||||
Headers defined here will be returned for every HTTP request to Icecast.
|
||||
|
||||
The ACAO header makes Icecast public content/API by default
|
||||
This will make streams easier embeddable (some HTML5 functionality needs it).
|
||||
Also it allows direct access to e.g. /status-json.xsl from other sites.
|
||||
If you don't want this, comment out the following line or read up on CORS.
|
||||
-->
|
||||
<http-headers>
|
||||
<header name="Access-Control-Allow-Origin" value="*" />
|
||||
<header name="X-Clacks-Overhead" value="GNU Terry Pratchett" />
|
||||
</http-headers>
|
||||
|
||||
|
||||
@ -103,12 +57,10 @@
|
||||
<!--<master-server-port>8001</master-server-port>-->
|
||||
<!--<master-update-interval>120</master-update-interval>-->
|
||||
<!--<master-password>hackme</master-password>-->
|
||||
|
||||
<!-- setting this makes all relays on-demand unless overridden, this is
|
||||
useful for master relays which do not have <relay> definitions here.
|
||||
The default is 0 -->
|
||||
<!--<relays-on-demand>1</relays-on-demand>-->
|
||||
|
||||
<!--
|
||||
<relay>
|
||||
<server>127.0.0.1</server>
|
||||
@ -122,38 +74,152 @@
|
||||
-->
|
||||
|
||||
|
||||
<!-- Mountpoints
|
||||
Only define <mount> sections if you want to use advanced options,
|
||||
like alternative usernames or passwords
|
||||
-->
|
||||
|
||||
<!-- Default settings for all mounts that don't have a specific <mount type="normal">.
|
||||
<!-- the default mount is the top of the fall-back chain
|
||||
anyone listening to something pushing to the default
|
||||
gets seomthing in our fallback chain, isntead.
|
||||
-->
|
||||
<mount type="default">
|
||||
<public>0</public>
|
||||
<!-- <intro>/server-wide-intro.ogg</intro> -->
|
||||
<max-listener-duration>3600</max-listener-duration>
|
||||
<!-- <max-listener-duration>3600</max-listener-duration> -->
|
||||
<username>live</username>
|
||||
<password>shredlivepassword</password>
|
||||
<authentication type="url">
|
||||
<option name="mount_add" value="http://auth.example.org/stream_start.php"/>
|
||||
</authentication>
|
||||
<http-headers>
|
||||
<header name="foo" value="bar" />
|
||||
</http-headers>
|
||||
<password>@@Source_Pass@@</password>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/live</fallback-mount>
|
||||
</mount>
|
||||
|
||||
<!-- <mount> -->
|
||||
<!-- <mount-name>/black.mp3</mount-name> -->
|
||||
<!-- <fallback-mount>/silver.mp3</fallback-mount> -->
|
||||
<!-- <fallback-override>1</fallback-override> -->
|
||||
<!-- </mount> -->
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/live.ogg</mount-name>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/gold.ogg</fallback-mount>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/gold.ogg</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/purple.ogg</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/purple.ogg</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/black.ogg</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/black.ogg</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/silver.ogg</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<!-- <intro>/server-wide-intro.ogg</intro> -->
|
||||
<!-- <max-listener-duration>3600</max-listener-duration> -->
|
||||
<mount-name>/silver.ogg</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/live.ogg</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
|
||||
<!-- <mount> -->
|
||||
<!-- <mount-name>/silver.mp3</mount-name> -->
|
||||
<!-- <fallback-mount>/black.mp3</fallback-mount> -->
|
||||
<!-- <fallback-override>1</fallback-override> -->
|
||||
<!-- </mount> -->
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<fallback-override>1</fallback-override>
|
||||
<mount-name>/live</mount-name>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/live.mp3</fallback-mount>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/live.mp3</mount-name>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/gold</fallback-mount>
|
||||
</mount>
|
||||
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/gold</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/gold.mp3</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/gold.mp3</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/gold.ogg</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/purple</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/purple.mp3</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/purple.mp3</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/black</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<!-- <intro>/server-wide-intro.ogg</intro> -->
|
||||
<!-- <max-listener-duration>3600</max-listener-duration> -->
|
||||
<mount-name>/black</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/black.mp3</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/black.mp3</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/silver</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<!-- <intro>/server-wide-intro.ogg</intro> -->
|
||||
<!-- <max-listener-duration>3600</max-listener-duration> -->
|
||||
<mount-name>/silver</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/silver.mp3</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
<mount type="normal">
|
||||
<public>0</public>
|
||||
<mount-name>/silver.mp3</mount-name>
|
||||
<fallback-override>1</fallback-override>
|
||||
<fallback-mount>/live</fallback-mount>
|
||||
<username>live</username>
|
||||
<password>@@Source_Pass@@</password>
|
||||
</mount>
|
||||
|
||||
<!-- Normal mounts -->
|
||||
<!--
|
||||
@ -202,16 +268,10 @@
|
||||
<fileserve>1</fileserve>
|
||||
|
||||
<paths>
|
||||
<!-- basedir is only used if chroot is enabled -->
|
||||
<basedir>/usr/share/icecast2</basedir>
|
||||
|
||||
<!-- Note that if <chroot> is turned on below, these paths must both
|
||||
be relative to the new root, not the original root -->
|
||||
<logdir>/var/log/icecast2</logdir>
|
||||
<webroot>/usr/share/icecast2/web</webroot>
|
||||
<adminroot>/usr/share/icecast2/admin</adminroot>
|
||||
<!-- <pidfile>/usr/share/icecast2/icecast.pid</pidfile> -->
|
||||
|
||||
<!-- Aliases: treat requests for 'source' path as being for 'dest' path
|
||||
May be made specific to a port or bound address using the "port"
|
||||
and "bind-address" attributes.
|
||||
@ -233,7 +293,7 @@
|
||||
<logging>
|
||||
<accesslog>access.log</accesslog>
|
||||
<errorlog>error.log</errorlog>
|
||||
<!-- <playlistlog>playlist.log</playlistlog> -->
|
||||
<playlistlog>playlist.log</playlistlog>
|
||||
<loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
|
||||
<logsize>10000</logsize> <!-- Max size of a logfile -->
|
||||
<!-- If logarchive is enabled (1), then when logsize is reached
|
||||
125
play.html
Normal file
125
play.html
Normal file
@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://code.jquery.com/jquery.min.js"></script>
|
||||
<script>
|
||||
function play() {
|
||||
var my = document.getElementById('player');
|
||||
my.currentTime = 0;
|
||||
/**this one loops***/
|
||||
if ($('.btn').find('span i').hasClass('fa-stop')) {
|
||||
$('.btn').find('span i').removeClass('fa-stop').addClass('fa-play-circle');
|
||||
$('.texto').text("Play");
|
||||
}
|
||||
if (my.paused) {
|
||||
my.play();
|
||||
} else {
|
||||
my.pause();
|
||||
my.currentTime = 0;
|
||||
}
|
||||
my.addEventListener("ended", function(e) {
|
||||
$('.btn').find('span i').removeClass('fa-play-circle').addClass('fa-stop');
|
||||
$('.texto').text("Stop");
|
||||
my.play();
|
||||
});
|
||||
}
|
||||
|
||||
async function updateTitle() {
|
||||
const url = "/json";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
//throw new Error(`Response status: ${response.status}`);
|
||||
} else {
|
||||
|
||||
const json = await response.json();
|
||||
//console.log(json);
|
||||
document.getElementById('title').innerText = json.title;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// document.shredIng = { title: "" };
|
||||
// function updateTitle() {
|
||||
// fetch("/js", {
|
||||
// headers: { 'Content-Type': 'application/json'
|
||||
// }
|
||||
// }).then(function(response) {
|
||||
// if(!response.ok) {
|
||||
// // oh no, an error. better do stuff!
|
||||
// }
|
||||
// else {
|
||||
// if(response.json && response.json.title) {
|
||||
// document.shredIng.title = response.json.title;
|
||||
|
||||
// document.getElementById('title').innerText = document.shredIng.title;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
setInterval(updateTitle, 7200);
|
||||
</script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Rubik+80s+Fade&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
html {
|
||||
background: #000;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
.fb {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 90vh;
|
||||
}
|
||||
.np {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
.bg {
|
||||
background: #000;
|
||||
background-image: linear-gradient(180deg,rgba(117, 117, 117, 1) 0%, rgba(110, 110, 110, 1) 17%, rgba(20, 20, 20, 1) 100%);
|
||||
}
|
||||
.rubik-80s-fade-regular {
|
||||
font-family: "Rubik 80s Fade", system-ui;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
font-family: "Rubik 80s Fade", system-ui;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Shred.ing</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="bg padding fb"><div style="text-align: center">
|
||||
<div class=="np bg" id="music" style="padding-left:.5rem;">
|
||||
<h1 style="font-size: 500%" class="np">Shred.ing</h1>
|
||||
<h2 style="font-size: 330%" class="np">Internet Radio</h2>
|
||||
<button type="button" class="btn btn-success" data-toggle="collapse" data-target="#player" onclick="play();">
|
||||
<!-- <span><i class="fa fa-play-circle" aria-hidden="true"></i>
|
||||
|
||||
<span class="texto">Play</span>
|
||||
</span> -->
|
||||
<audio controls id="player" class="collapse">
|
||||
<source src="https://shred.ing" type="audio/mp3">
|
||||
</audio>
|
||||
</button>
|
||||
|
||||
<div id="title" style="border: 1px dashed cyan; font-family: Arial, Helvetica, sans-serif; font-size: 150%; padding: .75rem; margin-top: .5rem; text-align: center; padding-top: .75rem; color: #3c3; filter: drop-shadow(1.6px 1.3px .25px #c3c);" class="">
|
||||
$Title$
|
||||
</div></div>
|
||||
</div>
|
||||
<script> updateTitle(); </script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user