Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add hls support #2794

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open

feat: add hls support #2794

wants to merge 27 commits into from

Conversation

mp3butcher
Copy link
Contributor

@mp3butcher mp3butcher commented Dec 1, 2023

Description

implement HLS .
rely on nginx to serve files as liquidsoap hls.harbor is not recommended for direct audience.
The cons is we loose listeners stats if hls.
a mount point have been created in nginx libretime.conf:

 location  /hls { 
     alias @@HLS_PLAYOUT_OUTPUT@@;
  }

Note

Testing

  • Tested on ubuntu 20.04 with vagrant
  • docker bullseye

Copy link

codecov bot commented Dec 1, 2023

Codecov Report

Attention: 9 lines in your changes are missing coverage. Please review.

Comparison is base (2a91320) 70.35% compared to head (c7e95fd) 70.44%.
Report is 4 commits behind head on main.

Files Patch % Lines
shared/libretime_shared/cli.py 0.00% 5 Missing ⚠️
playout/libretime_playout/liquidsoap/main.py 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2794      +/-   ##
==========================================
+ Coverage   70.35%   70.44%   +0.09%     
==========================================
  Files         149      149              
  Lines        4034     4067      +33     
==========================================
+ Hits         2838     2865      +27     
- Misses       1196     1202       +6     
Flag Coverage Δ
analyzer 46.91% <ø> (ø)
api 93.72% <ø> (ø)
api-client 64.40% <ø> (ø)
playout 47.79% <73.33%> (+0.39%) ⬆️
shared 88.48% <76.19%> (-0.62%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@mp3butcher mp3butcher changed the title Hls support feat(legacy) Hls support Dec 1, 2023
@mp3butcher mp3butcher changed the title feat(legacy) Hls support feat(legacy): Hls support Dec 1, 2023
@mp3butcher mp3butcher changed the title feat(legacy): Hls support feat(legacy): hls support Dec 1, 2023
@mp3butcher
Copy link
Contributor Author

mp3butcher commented Dec 1, 2023

i don't understand ci message (sorry I have versions problems with prettier...can't use git formatting)
https://github.com/libretime/libretime/actions/runs/7059733283/job/19217904794?pr=2794
if someone does, he'd be welcome...

@paddatrapper paddatrapper changed the title feat(legacy): hls support feat(playout): hls support Dec 3, 2023
@paddatrapper
Copy link
Contributor

I hope to properly test this in the coming weeks. Could you also please update the docs describing this feature and how to configure/use it?

@mp3butcher
Copy link
Contributor Author

mp3butcher commented Dec 12, 2023

I hope to properly test this in the coming weeks. Could you also please update the docs describing this feature and how to configure/use it?

The config file template is pretty self explanatory...HLS is composed of several streams with different quality embed in container with a format so you have to describe the container format and streams via a tuple (streamname,codec,bitrate)...
In the template i enable a hls output with 3 mp3 streams of differents quality....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make a function because output.file.hls varies accross liquidsoap versions

installer/nginx/libretime.conf Outdated Show resolved Hide resolved
shared/libretime_shared/config/_models.py Outdated Show resolved Hide resolved
shared/libretime_shared/config/_models.py Outdated Show resolved Hide resolved
shared/libretime_shared/config/_models.py Outdated Show resolved Hide resolved
@paddatrapper
Copy link
Contributor

Is there a way to stream HLS to nginx instead of doing it via a file?

@mp3butcher
Copy link
Contributor Author

mp3butcher commented Dec 13, 2023

Is there a way to stream HLS to nginx instead of doing it via a file?

http://nginx-rtmp.blogspot.com/2017/07/introducing-nginx-ts-module-for-hls-and.html can be a lead
It may be possible to stream with unsafe hls.harbor on publish and serve on play

@paddatrapper
Copy link
Contributor

After discussion, I think we should continue with the file-based solution instead - it is cleaner and induces less delay

@jooola jooola changed the title feat(playout): hls support feat: add hls support Dec 18, 2023
Copy link
Contributor

@jooola jooola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I made first pass.

I think we should implement a simple working HLS feature, and iterate to add more options. Supporting too many formats/codecs is also risky, let's do not diverge from the spec.

I already started working on HLS a while back, did you take a look at my PR: #2234

Comment on lines +301 to +302
$values['stream']['outputs']['shoutcast'],
$values['stream']['outputs']['hls']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not merge HLS streams in the icecast/shoutcast streams. We can benefit from a fresh/clean settings schema, and I don't see the benefit from merging this in the "merged" streams.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mandatory to do that, it doesn't work if i remove this line (merged is the array parsed in StreamSettings.php)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it mandatory? "It doesn't work" doesn't seem like a valid argument sorry 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Streams settings data (url,codec..) presented in the player are retrieved from this merged outputs array

shared/libretime_shared/config/_models.py Outdated Show resolved Hide resolved
shared/libretime_shared/config/_models.py Outdated Show resolved Hide resolved
shared/libretime_shared/config/_models.py Outdated Show resolved Hide resolved
legacy/application/models/StreamSetting.php Show resolved Hide resolved
Comment on lines 324 to 325
# > must be one of ('mpegts', 'mp3', 'adts', 'mp4')
# > this field is REQUIRED
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's reduce the amount of format for now, extra format can be added and tested in future PRs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AC3/ADTS is in the spec, further it work as it should with hls.js so i'll let it .

I'll remove mp4 because i haven't achieve anything with liquidsoap 1.4 even if in spec...:/

ok to remove mp3

Also, I'll will move format property as stream property to fit liquidsoap stream model (it was a mistake to put it as hls property)

edit mp4 seems to require movflags=+dash+skip_sidx+skip_trailer+frag_custom+global_header

installer/config.yml Outdated Show resolved Hide resolved
installer/config.yml Outdated Show resolved Hide resolved
install Outdated
@@ -628,6 +628,7 @@ link_python_app libretime-playout-notify

info "creating libretime-playout working directory"
mkdir_and_chown "$LIBRETIME_USER" "$WORKING_DIR/playout"
mkdir_and_chown "$LIBRETIME_USER" "$WORKING_DIR/playout/hls"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to have playout create the "$WORKING_DIR/playout/hls" directory, the "$WORKING_DIR/playout" is writable by libretime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the hls directory must be created before nginx starts so we can't let playout create this directory...no?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why ? We only read in this directory during a request, and response with 404 if no files are found. Sound doable to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you think it's safe to launch nginx and serve a not-yet-created directory, so i'm good with removing this line but it will require testing (with docker it's required -liquidsoap can't create output directory-)

Comment on lines 73 to 78
$result = array_merge($result, [
$prefix . 'port' => $_SERVER['SERVER_PORT'],
$prefix . 'host' => $_SERVER['SERVER_NAME'],
$prefix . 'type' => 'hls',
$prefix . 'bitrate' => '',
]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think we prefer to use the config public url and not the webserver configs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the present configuration, you can use both as with other outputs:

  • default is webserver
  • if public url is provided it's use instead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of the project doesn't rely on the web server configuration, this would diverge from the current expectation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you tell me to add settings for web server host/port?

Copy link
Contributor

@jooola jooola Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use the Config::get('general.public_url') (with the _raw key you get access to the URL object (League\Uri\Uri;).

if (!$result[$prefix . 'public_url']) {
$host = Config::get('general.public_url_raw')->getHost();
$port = $result[$prefix . 'port'];
$mount = $result[$prefix . 'mount'];
$result[$prefix . 'public_url'] = "http://{$host}:{$port}/{$mount}";
if ($result[$prefix . 'output'] == 'shoutcast') {
// The semi-colon is important to make Shoutcast stream URLs play instead turn into a page.
$result[$prefix . 'public_url'] .= ';';
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I think we create an new function and not use the backward compatible and complex Application_Model_StreamConfig::getOutput function.


{% for stream in output.streams -%}

streamout = %ffmpeg(format="{{output.format}}" ,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that %ffmpeg (as well as %audio for liquidsoap>2.0) arguments can't be dynamically passed through a function we can customize for different lq versions (as i did for output.file.hls).....So we can't maintain hls for both lq 1.4 and 2.0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the futur, if you really need to handle the %functions, you may use jinja templating and check against the version during the startup of playout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants