Search code examples
perlaudioffmpegffplayyt-dlp

yt-dlp get audio only link -> ffmpeg piped audio -> ffplay


Ok, i have a perl script that i am trying to figure out why it is throwing an io error. First i use yt-dlg to get the link of only the audio - this works as expected and i can navigate to the link in a browser just fine. then i open a ffmpeg pipe in perl and then try to read the output from ffmpeg and eventually, if i can get this working, i will process the ffmpeg output then send to a named pipe.

the problem comes from the ffmpeg when i am processing the data from the link obtained with yt-dlp, and i think it has to do with my while loop but i am not sure what. i have a named pipe called "input". i summon ffmpeg with the following:

#/usr/bin/perl
use strict;
use warnings;

my $file = /path/to/named/pipe
my $read_len = 1024;

open (my $SOURCE_AUDIO, '-|', "ffmpeg -y -i \'$link\' -map 0 -c copy -ac 2 -f opus -ar 48000 pipe:1");
binmode($SOURCE_AUDIO);

# process the ffmpeg output.i have a function i want to implement here, 
# but i need to be able to parse ffmpeg output in set read lengths

while( read($SOURCE_AUDIO, my $buf, $read_len)){
print $file $buf;
};

but before the end of the playback, somewhere around the end of the audio stream ffmpeg throws errors like this:

[tls @ 0x5d0de00] Error in the pull function..2kbits/s speed=1.21x
[tls @ 0x5d0de00] IO error: Connection reset by peer
[tls @ 0x5d0de00] The specified session has been invalidated for some reason.
    Last message repeated 1 times
https://rr3---sn-(truncated): Input/output error
size=    1021kB time=00:01:18.36 bitrate= 106.7kbits/s speed=1.21x
video:0kB audio:1012kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.808163%

i am not sure what is causing it to end early, or what is causing it to be terminated. i can download the file and re-encode it (if needed) and then play it flawlessly with ffplay, but i cannot, for the life of me, parse ffmpeg output and write it to a named pipe. any help sure would be appreciated. thanks

P.S. i am using latest updated windows 11 and WSL's built in perl:

This is perl 5, version 30, subversion 0 (v5.30.0) built for x86_64-linux-gnu-thread-multi
(with 50 registered patches, see perl -V for more detail)

Copyright 1987-2019, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Solution

  • i was able to get around this error by letting yt-dlp handle the downloading, then piped yt-dlp output to ffmpeg. then i was able to read ffmpeg output in my while loop:

    #!/usr/bin/perl
    use warnings;
    use strict;
    
    my $query = shift;
    
    open my $file, '+>', "/home/user/pipes/input" or die $!;
    binmode($file);
    
    # system("yt-dlp -q -f bestaudio[acodec=opus] ytsearch:'$query' -o - | ffmpeg -hide_banner -loglevel error -i pipe: -map 0 -c copy -ac 2 -f opus -ar 48000 pipe: | ffplay -i pipe:");
    
    open(my $SOURCE_AUDIO, '-|', "yt-dlp -q -f bestaudio[acodec=opus] ytsearch:'$query' -o - | ffmpeg -hide_banner -loglevel error -i pipe: -map 0 -c copy -ac 2 -f opus -ar 48000 pipe:");
    binmode($SOURCE_AUDIO);
    
    while ( <$SOURCE_AUDIO> ) {
        print $file $_;
        print length($_) . "\n"; # prints length of current data stream captured from ffmpeg
    }
    

    works as i would expect it to.