Jump to content

Recommended Posts

Posted

The LUA script yt-dlp4vlc reads the video quality preset by the user in VLC's settings only once while starting the player. If this setting is changed by the user at some point, the player has of course to be restarted to take the new setting into account. :P


Posted (edited)

Since the ytdlp-silent-xp.exe file for starting yt-dlp hidden provided by FalloNero is still not working, I modified the code again and cleaned up all unnecessary lines of code. From now on, my PowerShell command "PowerShell.exe -windowstyle hidden cmd /c &" will be executed in the case the hidecon.exe file doesn't exist. If, however, the hidecon.exe file is present in the main folder of VLC, my reduced hidecon command "hidecon &" will be used instead to start yt-dlp hidden. Here is my new mod of the LUA script yt-dlp4vlc:

-- YouTube Link Resolver for VLC with Separate Video and Audio URLs
-- Place this script in VLC's lua/playlist directory

local yt_dlp_path = 'yt-dlp.exe'
local yt_dlp_silent_path = 'hidecon.exe'

function sleep(s)
    local ntime = os.time() + s
    repeat until os.time() > ntime
end

function probe()
    -- Check if the input is a YouTube link
    return vlc.access == "http" or vlc.access == "https" and 
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))
end

function parse()
    -- Construct the full YouTube URL
    local youtube_url = vlc.access .. "://" .. vlc.path

    -- Extract "quality" query parameter if present
    local quality = youtube_url:match("[&?]quality=(%d+)[pP]?")
    youtube_url = youtube_url:gsub("[&?]quality=%d+[pP]?", ""):gsub("[&?]$", "") -- Remove trailing ? or &

    -- Get the preferred resolution preset by the user in VLC
    local prefres = vlc.var.inherit(nil, "preferred-resolution")
    if prefres < 0 then
        prefres = 2160 -- Best quality set to 2160p to overwrite VLC's native value of -1
    end

    local allowed_qualities = {
        ["240"] = true,
        ["360"] = true,
        ["480"] = true,
        ["720"] = true,
        ["1080"] = true,
        ["2160"] = true
    }

    -- Default quality limited to the preferred resolution taken from VLC's settings
    local format_string = string.format("bestvideo[height<=%i]+bestaudio", prefres)
  
    if quality and allowed_qualities[quality] then
        format_string = string.format("bestvideo[height<=%i]+bestaudio", quality)
        vlc.msg.info("Using requested quality: " .. quality .. "p")
    else
        vlc.msg.info("No valid quality specified. Defaulting to best available.")
    end

    local cmd_hidden = 'hidecon &' -- Start cmd hidden and ...
    -- No better codec than h264 (an important switch for older hardware). This can of course be changed by the users according to their needs.
    local codec_limit = '-S "codec:h264"'
    local video_url = ''
    local audio_url = ''

    local yt_dlp_silent_exists = io.open(yt_dlp_silent_path, "r") ~= nil
    if not yt_dlp_silent_exists then
        vlc.msg.info(yt_dlp_silent_path .. " not found. Falling back to " .. yt_dlp_path)
        cmd_hidden = 'PowerShell.exe -windowstyle hidden cmd /c &' -- Start cmd hidden and ...
        local cmd = string.format(
            '%s "%s" %s -f \"%s\" -g "%s"',
            cmd_hidden,
            yt_dlp_path,
            codec_limit,
            format_string,
            youtube_url
        )
        local handle = io.popen(cmd)
        video_url = handle:read("*l")
        audio_url = handle:read("*l")
        handle:close()
    else
        vlc.msg.info(yt_dlp_silent_path .. " found. Running program")
        local cmd = string.format(
            '%s "%s" %s -f \"%s\" -g "%s"',
            cmd_hidden,
            yt_dlp_path,
            codec_limit,
            format_string,
            youtube_url
        )
        local handle = io.popen(cmd)
        video_url = handle:read("*l")
        audio_url = handle:read("*l")
        handle:close()
    end

    video_url = video_url and video_url:gsub("^%s+", ""):gsub("%s+$", "") or ""
    audio_url = audio_url and audio_url:gsub("^%s+", ""):gsub("%s+$", "") or ""

    vlc.msg.info("[YouTube Resolver] Original URL: " .. youtube_url)
    vlc.msg.info("[YouTube Resolver] Video URL: " .. video_url)

    if audio_url and audio_url ~= "" then
        return {
            {
                path = video_url,
                name = vlc.path .. " (Video)",
                options = {
                    ":input-slave=" .. audio_url
                }
            }
        }
    else
        return {
            {
                path = video_url,
                name = vlc.path .. " (Video + Audio)"
            }
        }
    end
end


Cheers, AstroSkipper matrix.gif

Edited by AstroSkipper
Posted (edited)
On 1/3/2026 at 3:49 PM, AstroSkipper said:

Since the ytdlp-silent-xp.exe file for starting yt-dlp hidden provided by FalloNero is still not working, I modified the code again and cleaned up all unnecessary lines of code. From now on, my PowerShell command "PowerShell.exe -windowstyle hidden cmd /c &" will be executed in the case the hidecon.exe file doesn't exist. If, however, the hidecon.exe file is present in the main folder of VLC, my reduced hidecon command "hidecon &" will be used instead to start yt-dlp hidden. Here is my new mod of the LUA script yt-dlp4vlc:

-- YouTube Link Resolver for VLC with Separate Video and Audio URLs
-- Place this script in VLC's lua/playlist directory

local yt_dlp_path = 'yt-dlp.exe'
local yt_dlp_silent_path = 'hidecon.exe'

function sleep(s)
    local ntime = os.time() + s
    repeat until os.time() > ntime
end

function probe()
    -- Check if the input is a YouTube link
    return vlc.access == "http" or vlc.access == "https" and 
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))
end

function parse()
    -- Construct the full YouTube URL
    local youtube_url = vlc.access .. "://" .. vlc.path

    -- Extract "quality" query parameter if present
    local quality = youtube_url:match("[&?]quality=(%d+)[pP]?")
    youtube_url = youtube_url:gsub("[&?]quality=%d+[pP]?", ""):gsub("[&?]$", "") -- Remove trailing ? or &

    -- Get the preferred resolution preset by the user in VLC
    local prefres = vlc.var.inherit(nil, "preferred-resolution")
    if prefres < 0 then
        prefres = 2160 -- Best quality set to 2160p to overwrite VLC's native value of -1
    end

    local allowed_qualities = {
        ["240"] = true,
        ["360"] = true,
        ["480"] = true,
        ["720"] = true,
        ["1080"] = true,
        ["2160"] = true
    }

    -- Default quality limited to the preferred resolution taken from VLC's settings
    local format_string = string.format("bestvideo[height<=%i]+bestaudio", prefres)
  
    if quality and allowed_qualities[quality] then
        format_string = string.format("bestvideo[height<=%i]+bestaudio", quality)
        vlc.msg.info("Using requested quality: " .. quality .. "p")
    else
        vlc.msg.info("No valid quality specified. Defaulting to best available.")
    end

    local cmd_hidden = 'hidecon &' -- Start cmd hidden and ...
    -- No better codec than h264 (an important switch for older hardware). This can of course be changed by the users according to their needs.
    local codec_limit = '-S "codec:h264"'
    local video_url = ''
    local audio_url = ''

    local yt_dlp_silent_exists = io.open(yt_dlp_silent_path, "r") ~= nil
    if not yt_dlp_silent_exists then
        vlc.msg.info(yt_dlp_silent_path .. " not found. Falling back to " .. yt_dlp_path)
        cmd_hidden = 'PowerShell.exe -windowstyle hidden cmd /c &' -- Start cmd hidden and ...
        local cmd = string.format(
            '%s "%s" %s -f \"%s\" -g "%s"',
            cmd_hidden,
            yt_dlp_path,
            codec_limit,
            format_string,
            youtube_url
        )
        local handle = io.popen(cmd)
        video_url = handle:read("*l")
        audio_url = handle:read("*l")
        handle:close()
    else
        vlc.msg.info(yt_dlp_silent_path .. " found. Running program")
        local cmd = string.format(
            '%s "%s" %s -f \"%s\" -g "%s"',
            cmd_hidden,
            yt_dlp_path,
            codec_limit,
            format_string,
            youtube_url
        )
        local handle = io.popen(cmd)
        video_url = handle:read("*l")
        audio_url = handle:read("*l")
        handle:close()
    end

    video_url = video_url and video_url:gsub("^%s+", ""):gsub("%s+$", "") or ""
    audio_url = audio_url and audio_url:gsub("^%s+", ""):gsub("%s+$", "") or ""

    vlc.msg.info("[YouTube Resolver] Original URL: " .. youtube_url)
    vlc.msg.info("[YouTube Resolver] Video URL: " .. video_url)

    if audio_url and audio_url ~= "" then
        return {
            {
                path = video_url,
                name = vlc.path .. " (Video)",
                options = {
                    ":input-slave=" .. audio_url
                }
            }
        }
    else
        return {
            {
                path = video_url,
                name = vlc.path .. " (Video + Audio)"
            }
        }
    end
end


Cheers, AstroSkipper matrix.gif

For anyone who isn't familiar with LUA scripts. My mod of the LUA script yt-dlp4vlc does the following:

  • YouTube links entered in VLC are now processed by the YouTube downloader yt-dlp and are then transferred to VLC and played back. Credits to FalloNero.
  • The console window is hidden either by a PowerShell command or by the tool hidecon if the latter exists in VLC's programme folder.
  • Video links without appended quality parameter can now be played again with the quality preset by the user in the VLC settings.
  • The default video codec has been preset by me to h264 so that even older hardware is supported. This can of course be changed in the script by the users according to their needs.
Edited by AstroSkipper
Posted (edited)

As part of my work on ytBATCH, I have investigated many ffmpeg releases that are supposed to be compatible with Windows XP. These include, for example, the releases from @Reino, sherpya and @autodidact. The relatively new ones from @Reino and @autodidact work well with YouTube. But when it comes to TV streams, it's a completely different story. Their latest ones in particular have considerable problems with TV stream URLs. On my old Windows XP computer, negative performance changes are immediately apparent. FFmpeg 3.4.1 from 2017 is too old and can no longer access TV stream addresses. The newer releases 7.1 from 2024 and 8.1 from 2025 require much more CPU power than before. They are therefore problematic for older, weak Windows XP computers. That's why I still have been using ffmpeg releases from 2019 for TV stream addresses.

Edited by AstroSkipper
  • 3 weeks later...
Posted

For anyone struggling to navigate their way through this long thread and who just want some basic instructions getting the yt-dlp4vlc thing to work...

This is with VLC 3.0.23.0

Firstly, I had to install the yt-dlp4vlc script in C:\Program Files\VideoLAN\VLC\lua\playlist as a basic text file called youtube.luac (renaming the original youtube.luac out of the way). . . there may be a way of configuring VLC to use yt-dlp4vlc[.luac?] but don't ask me how.

Next up yt-dlp.exe running on XP. This one from October last year is working for me. . .

 https://github.com/nicolaasjan/yt-dlp/releases/download/2025.10.29.063241/yt-dlp_x86_winXP.exe

. . .which goes into C:\Program Files\VideoLAN\VLC renamed to yt-dlp.exe

That just leaves hidecon.exe (found in bin.x86-32) which also goes into C:\Program Files\VideoLAN\VLC

 http://code.kliu.org/misc/hidecon/hidecon-1.2.2-redist.7z

With that I was good to go.

Ben.
 

  • 2 weeks later...
Posted

Sorry to resurrect this again but I think the yt-dlp4vlc script has an error.

I think the probe function is incorrect . . .

function probe()
    -- Check if the input is a YouTube link
    return vlc.access == "http" or vlc.access == "https" and
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))

. . . should be . . .

function probe()
    -- Check if the input is a YouTube link
    return (vlc.access == "http" or vlc.access == "https") and
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))

. . . notice the brackets around the first 'or' pair.

Bit marginal but without those brackets any http url will return true.

Ben.

Posted
On 2/5/2026 at 3:26 PM, Ben Markson said:

Sorry to resurrect this again but I think the yt-dlp4vlc script has an error.

I think the probe function is incorrect . . .

function probe()
    -- Check if the input is a YouTube link
    return vlc.access == "http" or vlc.access == "https" and
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))

. . . should be . . .

function probe()
    -- Check if the input is a YouTube link
    return (vlc.access == "http" or vlc.access == "https") and
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))

. . . notice the brackets around the first 'or' pair.

Bit marginal but without those brackets any http url will return true.

Ben.

I think inserting the brackets is logical and correct.

  • 1 month later...
Guest sea
Posted (edited)
On 1/3/2026 at 3:49 PM, AstroSkipper said:
-- YouTube Link Resolver for VLC with Separate Video and Audio URLs
-- Place this script in VLC's lua/playlist directory

local yt_dlp_path = 'yt-dlp.exe'
local yt_dlp_silent_path = 'hidecon.exe'

function sleep(s)
    local ntime = os.time() + s
    repeat until os.time() > ntime
end

function probe()
    -- Check if the input is a YouTube link
    return vlc.access == "http" or vlc.access == "https" and 
           (string.match(vlc.path, "youtube%.com") or string.match(vlc.path, "youtu%.be"))
end

function parse()
    -- Construct the full YouTube URL
    local youtube_url = vlc.access .. "://" .. vlc.path

    -- Extract "quality" query parameter if present
    local quality = youtube_url:match("[&?]quality=(%d+)[pP]?")
    youtube_url = youtube_url:gsub("[&?]quality=%d+[pP]?", ""):gsub("[&?]$", "") -- Remove trailing ? or &

    -- Get the preferred resolution preset by the user in VLC
    local prefres = vlc.var.inherit(nil, "preferred-resolution")
    if prefres < 0 then
        prefres = 2160 -- Best quality set to 2160p to overwrite VLC's native value of -1
    end

    local allowed_qualities = {
        ["240"] = true,
        ["360"] = true,
        ["480"] = true,
        ["720"] = true,
        ["1080"] = true,
        ["2160"] = true
    }

    -- Default quality limited to the preferred resolution taken from VLC's settings
    local format_string = string.format("bestvideo[height<=%i]+bestaudio", prefres)
  
    if quality and allowed_qualities[quality] then
        format_string = string.format("bestvideo[height<=%i]+bestaudio", quality)
        vlc.msg.info("Using requested quality: " .. quality .. "p")
    else
        vlc.msg.info("No valid quality specified. Defaulting to best available.")
    end

    local cmd_hidden = 'hidecon &' -- Start cmd hidden and ...
    -- No better codec than h264 (an important switch for older hardware). This can of course be changed by the users according to their needs.
    local codec_limit = '-S "codec:h264"'
    local video_url = ''
    local audio_url = ''

    local yt_dlp_silent_exists = io.open(yt_dlp_silent_path, "r") ~= nil
    if not yt_dlp_silent_exists then
        vlc.msg.info(yt_dlp_silent_path .. " not found. Falling back to " .. yt_dlp_path)
        cmd_hidden = 'PowerShell.exe -windowstyle hidden cmd /c &' -- Start cmd hidden and ...
        local cmd = string.format(
            '%s "%s" %s -f \"%s\" -g "%s"',
            cmd_hidden,
            yt_dlp_path,
            codec_limit,
            format_string,
            youtube_url
        )
        local handle = io.popen(cmd)
        video_url = handle:read("*l")
        audio_url = handle:read("*l")
        handle:close()
    else
        vlc.msg.info(yt_dlp_silent_path .. " found. Running program")
        local cmd = string.format(
            '%s "%s" %s -f \"%s\" -g "%s"',
            cmd_hidden,
            yt_dlp_path,
            codec_limit,
            format_string,
            youtube_url
        )
        local handle = io.popen(cmd)
        video_url = handle:read("*l")
        audio_url = handle:read("*l")
        handle:close()
    end

    video_url = video_url and video_url:gsub("^%s+", ""):gsub("%s+$", "") or ""
    audio_url = audio_url and audio_url:gsub("^%s+", ""):gsub("%s+$", "") or ""

    vlc.msg.info("[YouTube Resolver] Original URL: " .. youtube_url)
    vlc.msg.info("[YouTube Resolver] Video URL: " .. video_url)

    if audio_url and audio_url ~= "" then
        return {
            {
                path = video_url,
                name = vlc.path .. " (Video)",
                options = {
                    ":input-slave=" .. audio_url
                }
            }
        }
    else
        return {
            {
                path = video_url,
                name = vlc.path .. " (Video + Audio)"
            }
        }
    end
end

your youtube vlc script didn't work for me at all and has endlessly looped with useless error messages. I was using my own custom path for yt-dlp and hidecon.exe

Then after debugging I found out that yt_dlp_silent_path (D://my path//hidecon.exe ) is not used at all and its directly forcing a  hidecon & which causes endless loops with useless error messages. I've fixed this with cmd_hidden = yt_dlp_silent_path .. ' &'

 

 

 

 

 

Edited by sea
  • 3 weeks later...
Posted (edited)

Im using:
 

  • VLC v3.0.23
  • hidecon.exe
  • youtube.luac (form this page)
  • yt-dlp.exe last ver for winxp

But i'm getting error/nothing (had to press two times "play" button to actually play it):

 
lua info: [YouTube Resolver] Original URL: https://www.youtube.com/watch?v=2sa4BT4Vuj4
lua info: [YouTube Resolver] Video URL: https://rr3---sn-w511uxa-n89l.googlevideo.com/videoplayback?expire=1776727765&ei=dWLmacnMC-7Qp-oPn8Cd4QE&ip=37.11.52.87&id=o-AAVf5HbHauKEmH-y7aaS2Na4kNpUUQkhOv6B55k6eJwz&itag=137&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&cps=416&met=1776706165%2C&mh=AG&mm=31%2C29&mn=sn-w511uxa-n89l%2Csn-h5qzen7y&ms=au%2Crdu&mv=m&mvi=3&pl=22&rms=au%2Cau&initcwndbps=2700000&bui=AUUZDGJOCyzre8j3RNa0ufGaFQzxCrhG_m40Zw1-AUQovvLy1w5z9c1bd2NPnLZxxyLnXOqmvKui3Ei_&spc=jlWavf1jE4lzYvHF-fLR5uN6p6h4BlTilsqYxeh4KuN5&vprv=1&svpuc=1&mime=video%2Fmp4&rqh=1&gir=yes&clen=318426352&dur=2107.400&lmt=1776136990766083&mt=1776705684&fvip=3&keepalive=yes&fexp=51565116%2C51565682&c=ANDROID_VR&txp=4432534&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AHEqNM4wRAIgKPlaPyHWLRUiP7d6cNKiE72r5qqwOxRGdgxGym_wMaoCIBFZ9J9-ctlWVRxefVxtPz2faDz3jVqLIRlSB351OSJK&lsparams=cps%2Cmet%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=APaTxxMwRQIgJfHg1uvt_s7RgUnHpWvX8vInYRhq9sq6gsRjvW2MwyUCIQDIbcvd27XTJ-lL4m1Ene5aIZOoKkUShf41K-qIFcoPIQ%3D%3D
mp4 info: Fragment sequence discontinuity detected 1 != 0
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
chain error: Too high level of recursion (3)
main error: Failed to create video converter
main error: Failed to create video converter
main error: Failed to create video converter
main error: Failed to adapt decoder format to display
main error: video output creation failed
main error: failed to create video output
dxva2 error: FindVideoServiceConversion failed

 

 

Edited by rocknard
x

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...