Skip to content

Commit

Permalink
Merge pull request #7 from mbugeia/liquidsoap-segfault
Browse files Browse the repository at this point in the history
Update liquidsoap to master
  • Loading branch information
mbugeia authored Dec 14, 2020
2 parents 70157d1 + 3084f6b commit 38dee29
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 126 deletions.
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ The goal of this program is to receive an audio stream with [SRT](https://github
srt2hls use [Liquidsoap](https://www.liquidsoap.info) to receive a stream and encode it in HLS, then it use [nginx] (https://www.nginx.com/) to serve HLS content.

The Liquidsoap container, by default, run radio/live.liq script. It's a fully functionnal example that will :
1. Receive an SRT input on port 10000
2. Encode it in aac with 3 quality
3. Segment it in HLS format in /hls directory
1. Receive 2 SRT inputs on ports 10000 and 10001
2. Create a production stream with basic logic between the 2 inputs
3. Encode the stream in aac with 3 quality
4. Segment it in HLS format in /hls directory

The Nginx container come with a specific configuration to serve HLS content with proper Content-Type, CORS and Cache-Control headers. It need read only access to /hls directory to serve HLS segments and playlists.

Expand All @@ -27,10 +28,8 @@ sudo docker-compose up

### Local installation requirements

[Liquidsoap](https://www.liquidsoap.info) 1.5.0+ (not released yet, use master)

ffmpeg compiled with fdkaac support (the one on liquidsoap debian/ubuntu repository is fine)

- [Liquidsoap](https://www.liquidsoap.info) 2.0.0+ (not released yet, use master)
- ffmpeg

## Basic usage

Expand Down Expand Up @@ -59,7 +58,7 @@ curl http://localhost:8080/api/get?livesource
### Sending audio to the streaming server

#### Using ffmpeg
Requirement : ffmpeg compiled with srt support (the one on liquidsoap debian/ubuntu repository is fine)
Requirement : ffmpeg compiled with srt support (https://johnvansickle.com/ffmpeg/ for example)

```bash
# static file
Expand Down
18 changes: 8 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@ services:
liquidsoap:
build:
context: liquidsoap
args:
gitbranch: master
version: 1.5.0
buildnumber: 2857
image: privyplace/liquidsoap:master-1.5.0-2857
image: privyplace/liquidsoap:master
container_name: liquidsoap
command: /radio/live.liq
restart: unless-stopped
networks:
- default
- default
expose:
- "8500"
- "8081"
Expand Down Expand Up @@ -41,10 +37,10 @@ services:
- ./hls:/hls
- ./nginxhls/stream.conf:/etc/nginx/conf.d/stream.conf
prometheus:
image: prom/prometheus:v2.19.3
image: prom/prometheus:v2.23.0
container_name: prometheus
volumes:
- ./monitoring/prometheus:/etc/prometheus
- ./monitoring/prometheus/:/etc/prometheus/
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
Expand Down Expand Up @@ -78,7 +74,7 @@ services:
labels:
org.label-schema.group: "monitoring"
grafana:
image: grafana/grafana:7.1.1
image: grafana/grafana:7.3.5
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
Expand All @@ -87,6 +83,7 @@ services:
- GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
- GF_LOG_LEVEL=warn
restart: unless-stopped
ports:
- 3000:3000/tcp
Expand All @@ -95,8 +92,9 @@ services:
labels:
org.label-schema.group: "monitoring"
cadvisor:
image: gcr.io/google-containers/cadvisor:v0.36.0
image: gcr.io/cadvisor/cadvisor:v0.37.0
container_name: cadvisor
privileged: true
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
Expand Down
27 changes: 4 additions & 23 deletions liquidsoap/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
FROM debian:buster-slim
FROM savonet/liquidsoap:master

ARG gitbranch
ARG version
ARG buildnumber

COPY liquidsoap.key /tmp/liquidsoap.key
USER root

ENV DEBIAN_FRONTEND noninteractive

RUN echo "\
deb http://deb.debian.org/debian buster main contrib non-free\n\
deb http://security.debian.org/debian-security buster/updates main contrib non-free\n\
deb http://deb.debian.org/debian buster-updates main contrib non-free\n\
" > /etc/apt/sources.list \
&& echo "\
Package: *\n\
Pin: origin deb.liquidsoap.info\n\
Pin-Priority: 900" > /etc/apt/preferences.d/liquidsoap \
&& apt-get update \
RUN apt-get update \
&& apt-get install -y \
gnupg2 \
ca-certificates \
dumb-init \
&& apt-key add /tmp/liquidsoap.key \
&& echo "deb http://deb.liquidsoap.info/debian stable main" > /etc/apt/sources.list.d/liquidsoap.list \
&& apt-get update \
&& apt-get install -y \
liquidsoap-"$gitbranch"=1:"$version"-"$buildnumber"~stable \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd -g 2000 radio \
&& useradd -m -u 2001 -g radio radio
Expand Down
49 changes: 0 additions & 49 deletions liquidsoap/liquidsoap.key

This file was deleted.

61 changes: 25 additions & 36 deletions radio/live.liq
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ set("clock.allow_streaming_errors",false)

# Retrieve configuration from environment

hlspath = ref getenv("HLSPATH")
hlspath = ref(getenv("HLSPATH"))

if !hlspath == "" then
hlspath := "/hls"
Expand All @@ -49,9 +49,9 @@ duration_unready_seconds_metric = prometheus.counter(labels=["radio","type","nam
is_blank_metric = prometheus.gauge(labels=["radio","type","name"],help="is source blank?","liquidsoap_is_blank")

# Prometheus metrics helpers
def check_if_ready(set_is_ready, increase_duration_unready_seconds, source) =
def check_if_ready(set_is_ready, increase_duration_unready_seconds, s) =
def callback() =
if source.is_ready(source) then
if s.is_ready() then
set_is_ready(1.)
else
set_is_ready(0.)
Expand All @@ -73,7 +73,7 @@ end

### Inputs

preferred_live_source = ref "srt1"
preferred_live_source = ref("srt1")

def check_if_preferred_livesource(set_is_preferred_livesource, source) =
def callback() =
Expand All @@ -87,7 +87,7 @@ def check_if_preferred_livesource(set_is_preferred_livesource, source) =
callback
end

srt1 = input.srt(id="input_srt1",
srt1 = input.srt(id="input_srt1",
port=10000)

# Get metrics
Expand All @@ -101,14 +101,14 @@ thread.run.recurrent(delay=0.,check_if_preferred_livesource(set_is_preferred_liv

# Wrap input in a buffer
srt1 = buffer(id="buffer_srt1",
fallible=true,
fallible=true,
max=3.0,
srt1)

# Tag source with it's name in metadata
srt1 = source_tag(srt1, "srt1")

srt2 = input.srt(id="input_srt2",
srt2 = input.srt(id="input_srt2",
port=10001)

# Get metrics
Expand All @@ -122,7 +122,7 @@ thread.run.recurrent(delay=0.,check_if_preferred_livesource(set_is_preferred_liv

# Wrap input in a buffer
srt2 = buffer(id="buffer_srt2",
fallible=true,
fallible=true,
max=3.0,
srt2)

Expand All @@ -144,9 +144,9 @@ def is_playing(n) =
fun () -> n == !preferred_live_source
end

live = switch(id="switch_live",
track_sensitive=false,
[(is_playing("srt1"), srt1),
live = switch(id="switch_live",
track_sensitive=false,
[(is_playing("srt1"), srt1),
(is_playing("srt2"), srt2)])

radio_prod = fallback(id="fallback_prod",
Expand Down Expand Up @@ -194,7 +194,7 @@ def blank_detect_handler() =
set_is_blank(1.0)
end

radio_prod = on_blank(id="on_blank_radio_prod",
radio_prod = blank.detect(id="on_blank_radio_prod",
max_blank=1.0,
min_noise=0.0,
on_noise=noise_detect_handler,
Expand All @@ -212,7 +212,7 @@ radio_prod = on_blank(id="on_blank_radio_prod",
# Define default http response
def http_response(level="error",msg="Unknow error",code=500) =
log.important(label="httplog", "#{level} #{msg} #{code}")
http_response(code=code,
http.response(code=code,
headers=[("Content-Type","application/json")],
data='{"level": #{json_of(level)}, "msg": #{json_of(msg)},"code": #{json_of(code)}}')
end
Expand Down Expand Up @@ -286,55 +286,46 @@ harbor.http.register(port=8081,method="GET","^/",httphandler)

# Define outputs formats

aac_lofi =
aac_lofi =
%ffmpeg(
format="mpegts",
%audio(
channels=2,
samplerate=44100,
codec="libfdk_aac",
codec="aac",
b="32k",
afterburner=1,
profile="aac_low"
)
)

aac_midfi =
aac_midfi =
%ffmpeg(
format="mpegts",
%audio(
channels=2,
samplerate=44100,
codec="libfdk_aac",
codec="aac",
b="96k",
afterburner=1,
profile="aac_low"
)
)

aac_hifi =
aac_hifi =
%ffmpeg(
format="mpegts",
%audio(
channels=2,
samplerate=44100,
codec="libfdk_aac",
codec="aac",
b="196k",
afterburner=1,
profile="aac_low"
)
)

# Defines stream infos that cannot be guessed by liqudisoap

streams_info = [("aac_lofi",(78000,"mp4a.40.2","ts")),
("aac_midfi",(160000,"mp4a.40.2","ts")),
("aac_hifi",(252000,"mp4a.40.2","ts"))]

# Output to HLS

def segment_name(~position,~extname,stream_name) =
timestamp = int_of_float(gettimeofday())
timestamp = int_of_float(time())
duration = 2
"#{stream_name}_#{duration}_#{timestamp}_#{position}.ts"
end
Expand All @@ -348,17 +339,15 @@ end
output.file.hls(id="output_hls",
playlist="live.m3u8",
segment_duration=2.0,
segments=3,
segments_overhead=10,
segments=5,
segments_overhead=5,
segment_name=segment_name,
streams_info=streams_info,
on_file_change=on_file_change,
persist=true,
persist_at="state.config",
!hlspath,
[("aac_lofi",aac_lofi),
("aac_midfi", aac_midfi),
[("aac_lofi",aac_lofi),
("aac_midfi", aac_midfi),
("aac_hifi", aac_hifi)],
radio_prod)

### END Outputs
### END Outputs

0 comments on commit 38dee29

Please sign in to comment.