glubsy / livestream_saver

Monitor a Youtube channel and download live-streams from the first segment
GNU General Public License v3.0
315 stars 39 forks source link

[Question] how to redirect output to another app like ffmpeg or a player like VLC? #71

Open JunioCalu opened 11 months ago

JunioCalu commented 11 months ago

how to redirect output to another app like ffmpeg or a player like VLC?

glubsy commented 11 months ago

Right now you cannot, because when downloading, every single segment is written to disk as a file. This could be improved, pull requests are welcome.

Since we are using yt-dlp to download currently, there might be some CLI options to enable that but I have no idea.

JunioCalu commented 10 months ago

Basically it is necessary to add the following lines in the configuration file. {'default': '-'} enables the output stream to buffer and logtostderr redirects the buffer to stderr.

 ydl_opts = {

    'outtmpl': {'default': '-'},
    'logtostderr': True,

 }

To use in practice:


Add the following configure lines to the livestreamsaver.cfg file:

ytdlp_command = yt-dlp -v --hls-prefer-native --hls-use-mpegts --no-part --retries 30 --no-break-per-input --wait-for-video 1000000 --fragment-retries "infinite" --retry-sleep linear=1::2 -f 'bestvideo[height<=720]+bestaudio/best[height<=720]' --cookies %COOKIES_PATH% %VIDEO_URL%


```python
python3 livestream_saver.py | mpv -

To redirect the buffer to a variable:

from yt_dlp import YoutubeDL
from contextlib import redirect_stdout
from pathlib import Path

youtube_id = "some-video-id"

ydl_opts = {
    'outtmpl': {'default': '-'},
    'logtostderr': True
}

buffer = io.BytesIO()
with redirect_stdout(buffer), YoutubeDL(ydl_opts) as foo:
    foo.download([youtube_id])

# write out the buffer for demonstration purposes
Path(f"{youtube_id}.mp4").write_bytes(buffer.getvalue())

Sources: https://github.com/yt-dlp/yt-dlp/issues/7837 https://github.com/yt-dlp/yt-dlp/issues/3298

glubsy commented 10 months ago

Ah, nice catch, thanks for the valuable information.

Although flushing to disk regularly would better than keeping everything in a long running memory buffer. Most devices would end up running out of available memory. As for simply sending to stdout, why not.

Side note: the ytdlp_command is only used for hooks, so it would spawn a separate process with your own yt-dlp. You would need to use --skip-download to avoid having two running downloads. Documentation is still not very good, sorry about that.

JunioCalu commented 10 months ago

Thanks for the note about --skip-download. Regarding the buffer its size can also be set using --buffer-size I think.

glubsy commented 10 months ago

Regarding the buffer its size can also be set using --buffer-size I think.

That's not how I understand the code you posted, the io.BytesIO buffer will collect all bytes yt-dlp sends to stdout (during the lifetime of the context) which means memory will keep getting allocated as long as the live stream is active. Anyway I know it was mostly an example but just wanted to point it out.