Using Streamlink to Listen to Lofi Girl Music Anytime, Anywhere

Listening to Lofi Girl music is very relaxing during breaks and study sessions. However, it requires accessing YouTube and keeping the webpage open to listen to real-time music. So, I wondered if I could directly stream the live content to my Alibaba Cloud server. This way, I wouldn’t need to use any proxies on my phone, and I wouldn’t have to keep YouTube playing in the background with premium access. I recently came across a tool called Streamlink that could serve this purpose. I thought of trying to redirect the stream to my Alibaba Cloud server so that I could play it using any media player.(English version Translated by GPT-3.5, 返回中文)

Prerequisites

  1. A foreign VPS host (with an unblocked IP) to receive and push the streaming, such as Bandwagon which is a good choice.
  2. A host within the country to receive and publish the stream, such as popular Alibaba Cloud in China.
  3. Nginx + rtmp-flv-module to create the streaming server.
  4. ffmpeg (I have tested pure streaming without transcoding, and the CPU usage is negligible).
  5. streamlink (not steamlink).

Note: For the foreign server, it is essential to choose CN2 or CMI routes to ensure stability with domestic connections. Otherwise, congestion in China can cause streaming interruptions.

Foreign Server Operations

I recommend placing this server on the CN2 GIA route in Los Angeles, USA, or the CMI route in Hong Kong. Of course, if you have the budget, you can choose the CN2 GIA route in Japan or Hong Kong. Make sure your Alibaba Cloud server can access it.

Connect to the Server

First, connect to your foreign server using SSH. Follow the streamlink documentation to install it. In my case, I have a Debian server, so I chose the Ubuntu installation method with the following commands:

1
2
sudo apt update
sudo apt install streamlink

Now that Streamlink is installed, you can start the streaming service. Use the following command:

1
streamlink --stream-url https://www.youtube.com/watch?v=YOUR_STREAM_KEY lofigirl best

Here’s an explanation of the above parameters:

  • YOUR_STREAM_KEY: Replace this with the actual stream key of the Lofi Girl channel.

After running the command, the console will display the output below, indicating that the stream has started. Although it shows the need to access 127.0.0.1, it actually listens on 0.0.0.0. Therefore, you can directly open VLC player and try to access it using the stream address.

1
2
3
4
5
6
7
[cli][info] Found matching plugin youtube for URL https://www.youtube.com/watch?v=YOUR_STREAM_KEY

Available streams: 144p (worst), 240p, 360p, ..., best (best)

Streamlink is running in local mode (--local-stream), file access to the streams is only enabled for the localhost. Livestreamer compatible URLs are:

http://127.0.0.1:30000/lofigirl/best

Use VLC to play the stream by entering the address http://YOUR_SERVER_IP:30000/lofigirl/best.

VLC Playing

With that, the first step is complete.

Install ffmpeg

To install ffmpeg, use the following command:

1
sudo apt install ffmpeg

If you don’t prefer using apt, you can also download the static files from Download FFmpeg - ffmpeg.org and place them in either /usr/bin or /usr/local/bin (you can also install ffmpeg within the domestic network to receive remote streams).

Domestic Server Operations

Next, we will move on to the domestic server operations. You need to install nginx on the domestic server (I know there are many other streaming servers, but I prefer using nginx).

I recommend compiling and installing nginx with the –add-module=../nginx-http-flv-module-1.2.9 parameter. Here’s the compilation command I used:

1
2
3
./configure --add-module=../nginx-http-flv-module-1.2.9
make
sudo make install

If your server already has a pre-compiled nginx, you can stop the current nginx service after running make in the nginx source code directory and copy the sources (objs/nginx) to $NGINX_HOME/sbin/nginx. Then, restart the nginx service. This will update nginx easily.

Edit Configuration

Open nginx.conf and add the following configuration at the same level as http {}:

1
2
3
4
5
6
7
8
9
10
11
rtmp_auto_push on;
rtmp {
server {
listen 1935;
application lofigirl {
live on;
record off;
push rtmp://YOUR_ALIBABA_CLOUD_IP/lofigirl;
}
}
}

Let me explain the above configuration:

  • YOUR_ALIBABA_CLOUD_IP: Replace this with the IP address of your Alibaba Cloud server.

Once the configuration is in place, run nginx -s reload to start the streaming server.

Back to the Foreign Server

Start Pushing the Stream

Now that we have installed nginx and ffmpeg, we can use ffmpeg to achieve our goal. We’ve been continuously streaming using streamlink. Now, we need ffmpeg to push that stream to Alibaba Cloud, where the rtmp module of the Alibaba Cloud nginx will receive it.

1
ffmpeg -i http://127.0.0.1:30000/lofigirl/best -c copy -f flv rtmp://YOUR_ALIBABA_CLOUD_IP/lofigirl

In the above command, replace YOUR_ALIBABA_CLOUD_IP with the IP address of your Alibaba Cloud server.

After running the command, you will see the following output:

1
2
3
4
5
6
7
[flv @ 0x55a9766e03c0] Failed to update header with correct duration.

Removing original stream_due: EOF st: 0 type: video side_data_only: 0

[h264 @ 0x55a9766e0cc0] mmco: unref short failure

[h264 @ 0x55a9766e0cc0] decode_slice_header error

You will also notice that files have been created in the target directory /opt/lofi-stream-hls.

HLS Streaming Explained

In simple terms, HLS (HTTP Live Streaming) continuously generates video file segments in a specified directory (referred to as the segment-video folder). These segments are .ts (Transport Stream) files encoded with H.264. The duration of each file is determined by the hls_fragment configuration setting. You can download these video files and play them directly. The delay depends on this duration. For example, when a live stream starts, the segment-video folder will generate 1.ts, 2.ts, 3.ts, representing 0-3 seconds, 3-6 seconds, and 6-9 seconds of the recording, respectively. It also contains a file named live.m3u8, which records the current sequence of the recordings. This playlist is continuously updated. Once the total duration of the current recordings reaches the hls_playlist_length setting (in this case, 24 seconds), it means that a maximum of 8 recordings will be stored at the same time. When the 9th recording (9.ts) arrives, representing 24-27 seconds, 1.ts will be automatically deleted. This ensures that the current folder always contains recordings of the last 24 seconds. The live.m3u8 file is then updated to remove 1.ts and add 9.ts (the new sequence will not start from 1.ts; it usually starts from a few sequences before the newest one). This results in a delay of 24 seconds for the video. If it starts from the few sequences before the newest one, the delay will be less than 10 seconds. During playback, the player reads the live.m3u8 file and plays the recordings in order. As the playlist is about to finish, the player refreshes the m3u8 file. At this point, the m3u8 playlist will be updated, and new contents will be appended to the end of the current playlist. However, the user has no control over this playlist. The live.m3u8 file is constantly updated, the playlist is continuously obtained from the m3u8 file, and new recordings are continuously played, thus achieving the live streaming effect. Therefore, the delay in live streaming depends on the length of the m3u8 playlist and the duration of each video segment. Increasing the length of the video segment may increase buffering time and server bandwidth pressure, while reducing the segment length may lead to a significant increase in the number of connections due to frequent requests for new files. Generally, a segment length of 2-5 seconds is suitable.

Configure Nginx to Allow Other Programs to Access the m3u8 Files

In nginx.conf, add the following configuration in the http -> server section:

1
2
3
4
5
6
location /lofi-stream-hls {
types{
application/vnd.apple.mpegurl m3u8;
}
alias /opt/lofi-stream-hls;
}

Restart nginx (taking care of permissions). Now, you can access the m3u8 files by using VLC and visiting http://YOUR_SERVER_IP/lofi-stream-hls/live.m3u8. You can play it in the background anytime and anywhere without needing YouTube Premium or any proxies.

Appendix: Complete Nginx Configuration

The complete nginx.conf configuration is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
worker_processes  1;
events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

sendfile on;

keepalive_timeout 65;

server {
listen 80;
server_name localhost;

location / {
root html;
index index.html index.htm;
}

location /lofi-stream-hls {
types{
application/vnd.apple.mpegurl m3u8;
}
alias /opt/lofi-stream-hls;
}
}
}

Appendix: Pure Audio ffmpeg Commands

1
2
3
ffmpeg -hide_banner -i http://127.0.0.1:30000/lofigirl/best -map 0 -c copy -f segment -segment_time 10 -reset_timestamps 1 "output%d.mp3"

ffmpeg -hide_banner -i http://127.0.0.1:30000/lofigirl/best -vn -c copy -f segment -segment_time 10 -reset_timestamps 1 "output%d.mp3"

Appendix: Service Examples

ffmpeg-stream.service

Create a file named ffmpeg-stream.service with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=ffmpeg stream service
After=network.target

[Service]
ExecStart=/usr/local/bin/ffmpeg -i http://127.0.0.1:30000/lofigirl/best -c copy -f flv rtmp://YOUR_ALIBABA_CLOUD_IP/lofigirl
WorkingDirectory=/usr/local/bin/
StandardOutput=inherit
StandardError=inherit
Restart=always
User=nobody
Group=nogroup

[Install]
WantedBy=multi-user.target

Create a file named lofi-streamlink.service with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=lofi streamlink service
After=network.target

[Service]
ExecStart=/usr/local/bin/streamlink --stream-url https://www.youtube.com/watch?v=YOUR_STREAM_KEY lofigirl best
WorkingDirectory=/usr/local/bin/
StandardOutput=inherit
StandardError=inherit
Restart=always
User=nobody
Group=nogroup

[Install]
WantedBy=multi-user.target

Appendix: References

STLInku - Building a YouTube Live Broadcasting Forwarding System - github.com