דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
ס

סגנון

@סגנון
אודות
פוסטים
90
נושאים
21
שיתופים
0
קבוצות
0
עוקבים
0
עוקב אחרי
0

פוסטים

פוסטים אחרונים הגבוה ביותר שנוי במחלוקת

  • בקשת מידע | איך עושים שנגן VLC יוכל להזרים סרטים מיוטיוב
    ס סגנון

    לא צריך, מצאתי לבד

    כאן:
    https://www.mekan0.com/iw/your-entries-cannot-be-opened/

    ובתמצות משם:

    לחפש במחשב את תיקיית: C:\Program Files (x86)\VideoLAN\VLC\lua\playlist (או משהו דומה)
    למצוא שם את הקובץ youtube.luac
    להחליף את תוכנו בתוכן מהקישור הזה: https://github.com/videolan/vlc/blob/master/share/lua/playlist/youtube.lua

    וזהו. הנגן מוכן לנגן יוטיוב.

    להלן התוכן:

    --[[
     Copyright © 2007-2023 the VideoLAN team
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
    --]]
    
    -- Helper function to get a parameter's value in a URL
    function get_url_param( url, name )
        local _, _, res = string.find( url, "[&?]"..name.."=([^&]*)" )
        return res
    end
    
    -- Helper function to copy a parameter when building a new URL
    function copy_url_param( url, name )
        local value = get_url_param( url, name )
        return ( value and "&"..name.."="..value or "" ) -- Ternary operator
    end
    
    function get_arturl()
        local iurl = get_url_param( vlc.path, "iurl" )
        if iurl then
            return iurl
        end
        local video_id = get_url_param( vlc.path, "v" )
        if not video_id then
            return nil
        end
        return vlc.access.."://img.youtube.com/vi/"..video_id.."/default.jpg"
    end
    
    -- Pick the most suited format available
    function get_fmt( fmt_list )
        local prefres = vlc.var.inherit(nil, "preferred-resolution")
        if prefres < 0 then
            return nil
        end
    
        local fmt = nil
        for itag,height in string.gmatch( fmt_list, "(%d+)/%d+x(%d+)[^,]*" ) do
            -- Apparently formats are listed in quality
            -- order, so we take the first one that works,
            -- or fallback to the lowest quality
            fmt = itag
            if tonumber(height) <= prefres then
                break
            end
        end
        return fmt
    end
    
    -- Helper emulating vlc.readline() to work around its failure on
    -- very long lines (see #24957)
    function read_long_line()
        local eol
        local pos = 0
        local len = 32768
        repeat
            len = len * 2
            local line = vlc.peek( len )
            if not line then return nil end
            eol = string.find( line, "\n", pos + 1 )
            pos = len
        until eol or len >= 1024 * 1024 -- No EOF detection, loop until limit
        return vlc.read( eol or len )
    end
    
    -- Buffering iterator to parse through the HTTP stream several times
    -- without making several HTTP requests
    function buf_iter( s )
        s.i = s.i + 1
        local line = s.lines[s.i]
        if not line then
            -- Put back together statements split across several lines,
            -- otherwise we won't be able to parse them
            repeat
                local l = s.stream:readline()
                if not l then break end
                line = line and line..l or l -- Ternary operator
            until string.match( line, "};$" )
    
            if line then
                s.lines[s.i] = line
            end
        end
        return line
    end
    
    -- Helper to search and extract code from javascript stream
    function js_extract( js, pattern )
        js.i = 0 -- Reset to beginning
        for line in buf_iter, js do
            local ex = string.match( line, pattern )
            if ex then
                return ex
            end
        end
        return nil
    end
    
    -- Descramble the "n" parameter using the javascript code that does that
    -- in the web page
    function n_descramble( nparam, js )
        if not js.stream then
            if not js.url then
                return nil
            end
            js.stream = vlc.stream( js_url )
            if not js.stream then
                -- Retry once for transient errors
                js.stream = vlc.stream( js_url )
                if not js.stream then
                    return nil
                end
            end
        end
    
        -- Look for the descrambler function's name
        -- a.C&&(b=a.get("n"))&&(b=Bpa[0](b),a.set("n",b),Bpa.length||iha(""))}};
        -- var Bpa=[iha];
        local callsite = js_extract( js, '[^;]*%.set%("n",[^};]*' )
        if not callsite then
            vlc.msg.dbg( "Couldn't extract YouTube video throttling parameter descrambling function name" )
            return nil
        end
    
        -- Try direct function name from following clause
        local descrambler = string.match( callsite, '%.set%("n",.%),...?%.length||(...?)%(' )
        local itm = nil
        if not descrambler then
            -- Try from main call site
            descrambler = string.match( callsite, '[=%(,&|]([a-zA-Z0-9_$%[%]]+)%(.%),.%.set%("n",' )
            if descrambler then
                -- Check if this is only an intermediate variable
                itm = string.match( descrambler, '^([^%[%]]+)%[' )
                if itm then
                    descrambler = nil
                end
            else
                -- Last chance: intermediate variable in following clause
                itm = string.match( callsite, '%.set%("n",.%),(...?)%.length' )
            end
        end
    
        if not descrambler and itm then
            -- Resolve intermediate variable
            descrambler = js_extract( js, 'var '..itm..'=%[(...?)[%],]' )
        end
    
        if not descrambler then
            vlc.msg.dbg( "Couldn't extract YouTube video throttling parameter descrambling function name" )
            return nil
        end
    
        -- Fetch the code of the descrambler function
        -- lha=function(a){var b=a.split(""),c=[310282131,"KLf3",b,null,function(d,e){d.push(e)},-45817231, [data and transformations...] ,1248130556];c[3]=c;c[15]=c;c[18]=c;try{c[40](c[14],c[2]),c[25](c[48]),c[21](c[32],c[23]), [scripted calls...] ,c[25](c[33],c[3])}catch(d){return"enhanced_except_4ZMBnuz-_w8_"+a}return b.join("")};
        local code = js_extract( js, "^"..descrambler.."=function%([^)]*%){(.-)};" )
        if not code then
            vlc.msg.dbg( "Couldn't extract YouTube video throttling parameter descrambling code" )
            return nil
        end
    
        -- Split code into two main sections: 1/ data and transformations,
        -- and 2/ a script of calls
        local datac, script = string.match( code, "c=%[(.*)%];.-;try{(.*)}catch%(" )
        if ( not datac ) or ( not script ) then
            vlc.msg.dbg( "Couldn't extract YouTube video throttling parameter descrambling rules" )
            return nil
        end
    
        -- Split "n" parameter into a table as descrambling operates on it
        -- as one of several arrays
        local n = {}
        for c in string.gmatch( nparam, "." ) do
            table.insert( n, c )
        end
    
        -- Helper
        local table_len = function( tab )
            local len = 0
            for i, val in ipairs( tab ) do
                len = len + 1
            end
            return len
        end
    
        -- Shared core section of compound transformations: it compounds
        -- the "n" parameter with an input string, character by character,
        -- using a Base64 alphabet as algebraic modulo group.
        -- var h=f.length;d.forEach(function(l,m,n){this.push(n[m]=f[(f.indexOf(l)-f.indexOf(this[m])+m+h--)%f.length])},e.split(""))
        local compound = function( ntab, str, alphabet )
            if ntab ~= n or
               type( str ) ~= "string" or
               type( alphabet ) ~= "string" then
                return true
            end
            local input = {}
            for c in string.gmatch( str, "." ) do
                table.insert( input, c )
            end
    
            local len = string.len( alphabet )
            for i, c in ipairs( ntab ) do
                if type( c ) ~= "string" then
                    return true
                end
                local pos1 = string.find( alphabet, c, 1, true )
                local pos2 = string.find( alphabet, input[i], 1, true )
                if ( not pos1 ) or ( not pos2 ) then
                    return true
                end
                local pos = ( pos1 - pos2 ) % len
                local newc = string.sub( alphabet, pos + 1, pos + 1 )
                ntab[i] = newc
                table.insert( input, newc )
            end
        end
    
        -- The data section contains among others function code for a number
        -- of transformations, most of which are basic array operations.
        -- We can match these functions' code to identify them, and emulate
        -- the corresponding transformations.
        local trans = {
            reverse = {
                func = function( tab )
                    local len = table_len( tab )
                    local tmp = {}
                    for i, val in ipairs( tab ) do
                        tmp[len - i + 1] = val
                    end
                    for i, val in ipairs( tmp ) do
                        tab[i] = val
                    end
                end,
                match = {
                    -- function(d){d.reverse()}
                    -- function(d){for(var e=d.length;e;)d.push(d.splice(--e,1)[0])}
                    "^function%(d%)",
                }
            },
            append = {
                func = function( tab, val )
                    table.insert( tab, val )
                end,
                match = {
                    -- function(d,e){d.push(e)}
                    "^function%(d,e%){d%.push%(e%)},",
                }
            },
            remove = {
                func = function( tab, i )
                    if type( i ) ~= "number" then
                        return true
                    end
                    i = i % table_len( tab )
                    table.remove( tab, i + 1 )
                end,
                match = {
                    -- function(d,e){e=(e%d.length+d.length)%d.length;d.splice(e,1)}
                    "^[^}]-;d%.splice%(e,1%)},",
                }
            },
            swap = {
                func = function( tab, i )
                    if type( i ) ~= "number" then
                        return true
                    end
                    i = i % table_len( tab )
                    local tmp = tab[1]
                    tab[1] = tab[i + 1]
                    tab[i + 1] = tmp
                end,
                match = {
                    -- function(d,e){e=(e%d.length+d.length)%d.length;var f=d[0];d[0]=d[e];d[e]=f}
                    -- function(d,e){e=(e%d.length+d.length)%d.length;d.splice(0,1,d.splice(e,1,d[0])[0])}
                    "^[^}]-;var f=d%[0%];d%[0%]=d%[e%];d%[e%]=f},",
                    "^[^}]-;d%.splice%(0,1,d%.splice%(e,1,d%[0%]%)%[0%]%)},",
                }
            },
            rotate = {
                func = function( tab, shift )
                    if type( shift ) ~= "number" then
                        return true
                    end
                    local len = table_len( tab )
                    shift = shift % len
                    local tmp = {}
                    for i, val in ipairs( tab ) do
                        tmp[( i - 1 + shift ) % len + 1] = val
                    end
                    for i, val in ipairs( tmp ) do
                        tab[i] = val
                    end
                end,
                match = {
                    -- function(d,e){for(e=(e%d.length+d.length)%d.length;e--;)d.unshift(d.pop())}
                    -- function(d,e){e=(e%d.length+d.length)%d.length;d.splice(-e).reverse().forEach(function(f){d.unshift(f)})}
                    "^[^}]-d%.unshift%(d.pop%(%)%)},",
                    "^[^}]-d%.unshift%(f%)}%)},",
                }
            },
            -- Here functions with no arguments are not really functions,
            -- they're constants: treat them as such. These alphabets are
            -- passed to and used by the compound transformations.
            alphabet1 = {
                func = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_",
                match = {
                    -- function(){for(var d=64,e=[];++d-e.length-32;){switch(d){case 91:d=44;continue;case 123:d=65;break;case 65:d-=18;continue;case 58:d=96;continue;case 46:d=95}e.push(String.fromCharCode(d))}return e}
                    "^function%(%){[^}]-case 58:d=96;",
                }
            },
            alphabet2 = {
                func = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
                match = {
                    -- function(){for(var d=64,e=[];++d-e.length-32;){switch(d){case 58:d-=14;case 91:case 92:case 93:continue;case 123:d=47;case 94:case 95:case 96:continue;case 46:d=95}e.push(String.fromCharCode(d))}return e}
                    -- function(){for(var d=64,e=[];++d-e.length-32;)switch(d){case 46:d=95;default:e.push(String.fromCharCode(d));case 94:case 95:case 96:break;case 123:d-=76;case 92:case 93:continue;case 58:d=44;case 91:}return e}
                    "^function%(%){[^}]-case 58:d%-=14;",
                    "^function%(%){[^}]-case 58:d=44;",
                }
            },
            -- Compound transformations are based on a shared core section
            -- that compounds the "n" parameter with an input string,
            -- character by character, using a variation of a Base64
            -- alphabet as algebraic modulo group.
            compound = {
                func = compound,
                match = {
                    -- function(d,e,f){var h=f.length;d.forEach(function(l,m,n){this.push(n[m]=f[(f.indexOf(l)-f.indexOf(this[m])+m+h--)%f.length])},e.split(""))}
                    "^function%(d,e,f%)",
                }
            },
            -- These compound transformation variants first build their
            -- Base64 alphabet themselves, before using it.
            compound1 = {
                func = function( ntab, str )
                    return compound( ntab, str, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_" )
                end,
                match = {
                    -- function(d,e){for(var f=64,h=[];++f-h.length-32;)switch(f){case 58:f=96;continue;case 91:f=44;break;case 65:f=47;continue;case 46:f=153;case 123:f-=58;default:h.push(String.fromCharCode(f))} [ compound... ] }
                    "^function%(d,e%){[^}]-case 58:f=96;",
                }
            },
            compound2 = {
                func = function( ntab, str )
                    return compound( ntab, str,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" )
                end,
                match = {
                    -- function(d,e){for(var f=64,h=[];++f-h.length-32;){switch(f){case 58:f-=14;case 91:case 92:case 93:continue;case 123:f=47;case 94:case 95:case 96:continue;case 46:f=95}h.push(String.fromCharCode(f))} [ compound... ] }
                    -- function(d,e){for(var f=64,h=[];++f-h.length-32;)switch(f){case 46:f=95;default:h.push(String.fromCharCode(f));case 94:case 95:case 96:break;case 123:f-=76;case 92:case 93:continue;case 58:f=44;case 91:} [ compound... ] }
                    "^function%(d,e%){[^}]-case 58:f%-=14;",
                    "^function%(d,e%){[^}]-case 58:f=44;",
                }
            },
            -- Fallback
            unid = {
                func = function( )
                    vlc.msg.dbg( "Couldn't apply unidentified YouTube video throttling parameter transformation, aborting descrambling" )
                    return true
                end,
                match = {
                }
            },
        }
    
        -- The data section actually mixes input data, reference to the
        -- "n" parameter array, and self-reference to its own array, with
        -- transformation functions used to modify itself. We parse it
        -- as such into a table.
        local data = {}
        datac = datac..","
        while datac and datac ~= "" do
            local el = nil
            -- Transformation functions
            if string.match( datac, "^function%(" ) then
                for name, tr in pairs( trans ) do
                    for i, match in ipairs( tr.match ) do
                        if string.match( datac, match ) then
                            el = tr.func
                            break
                        end
                    end
                    if el then
                        break
                    end
                end
                if not el then
                    el = trans.unid.func
                    vlc.msg.warn( "Couldn't parse unidentified YouTube video throttling parameter transformation" )
                end
    
                -- Compounding functions use a subfunction, so we need to be
                -- more specific in how much parsed data we consume.
                if el == trans.compound.func or
                   el == trans.compound1.func or
                   el == trans.compound2.func then
                    datac = string.match( datac, '^.-},e%.split%(""%)%)},(.*)$' )
                            or string.match( datac, "^.-},(.*)$" )
                else
                    datac = string.match( datac, "^.-},(.*)$" )
                end
    
            -- String input data
            elseif string.match( datac, '^"[^"]*",' ) then
                el, datac = string.match( datac, '^"([^"]*)",(.*)$' )
            -- Integer input data
            -- 1818016376,-648890305,-1200559E3, ...
            elseif string.match( datac, '^%-?%d+,' ) or
                   string.match( datac, '^%-?%d+[eE]%-?%d+,' ) then
                el, datac = string.match( datac, "^(.-),(.*)$" )
                el = tonumber( el )
            -- Reference to "n" parameter array
            elseif string.match( datac, '^b,' ) then
                el = n
                datac = string.match( datac, "^b,(.*)$" )
            -- Replaced by self-reference to data array after its declaration
            elseif string.match( datac, '^null,' ) then
                el = data
                datac = string.match( datac, "^null,(.*)$" )
            else
                vlc.msg.warn( "Couldn't parse unidentified YouTube video throttling parameter descrambling data" )
                el = false -- Lua tables can't contain nil values
                datac = string.match( datac, "^[^,]-,(.*)$" )
            end
    
            table.insert( data, el )
        end
    
        -- Debugging helper to print data array elements
        local prd = function( el, tab )
            if not el then
                return "???"
            elseif el == n then
                return "n"
            elseif el == data then
                return "data"
            elseif type( el ) == "string" then
                return '"'..el..'"'
            elseif type( el ) == "number" then
                el = tostring( el )
                if type( tab ) == "table" then
                    el = el.." -> "..( el % table_len( tab ) )
                end
                return el
            else
                for name, tr in pairs( trans ) do
                    if el == tr.func then
                        return name
                    end
                end
                return tostring( el )
            end
        end
    
        -- The script section contains a series of calls to elements of
        -- the data section array onto other elements of it: calls to
        -- transformations, with a reference to the data array itself or
        -- the "n" parameter array as first argument, and often input data
        -- as a second argument. We parse and emulate those calls to follow
        -- the descrambling script.
        -- c[40](c[14],c[2]),c[25](c[48]),c[14](c[1],c[24],c[42]()), [...]
        if not string.match( script, "c%[(%d+)%]%(c%[(%d+)%]([^)]-)%)" ) then
            vlc.msg.dbg( "Couldn't parse and execute YouTube video throttling parameter descrambling rules" )
            return nil
        end
        for ifunc, itab, args in string.gmatch( script, "c%[(%d+)%]%(c%[(%d+)%]([^)]-)%)" ) do
            local iarg1 = string.match( args, "^,c%[(%d+)%]" )
            local iarg2 = string.match( args, "^,[^,]-,c%[(%d+)%]" )
    
            local func = data[tonumber( ifunc ) + 1]
            local tab = data[tonumber( itab ) + 1]
            local arg1 = iarg1 and data[tonumber( iarg1 ) + 1]
            local arg2 = iarg2 and data[tonumber( iarg2 ) + 1]
    
            -- Uncomment to debug transformation chain
            --vlc.msg.err( '"n" parameter transformation: '..prd( func ).."("..prd( tab )..( arg1 ~= nil and ( ", "..prd( arg1, tab ) ) or "" )..( arg2 ~= nil and ( ", "..prd( arg2, tab ) ) or "" )..") "..ifunc.."("..itab..( iarg1 and ( ", "..iarg1 ) or "" )..( iarg2 and ( ", "..iarg2 ) or "" )..")" )
            --local nprev = table.concat( n )
    
            if type( func ) ~= "function" or type( tab ) ~= "table"
                or func( tab, arg1, arg2 ) then
                vlc.msg.dbg( "Invalid data type encountered during YouTube video throttling parameter descrambling transformation chain, aborting" )
                vlc.msg.dbg( "Couldn't descramble YouTube throttling URL parameter: data transfer will get throttled" )
                vlc.msg.err( "Couldn't process youtube video URL, please check for updates to this script" )
                break
            end
    
            -- Uncomment to debug transformation chain
            --local nnew = table.concat( n )
            --if nprev ~= nnew then
            --    vlc.msg.dbg( '"n" parameter transformation: '..nprev.." -> "..nnew )
            --end
        end
    
        return table.concat( n )
    end
    
    -- Descramble the URL signature using the javascript code that does that
    -- in the web page
    function sig_descramble( sig, js )
        if not js.stream then
            if not js.url then
                return nil
            end
            js.stream = vlc.stream( js.url )
            if not js.stream then
                -- Retry once for transient errors
                js.stream = vlc.stream( js.url )
                if not js.stream then
                    return nil
                end
            end
        end
    
        -- Look for the descrambler function's name
        -- if(h.s){var l=h.sp,m=wja(decodeURIComponent(h.s));f.set(l,encodeURIComponent(m))}
        -- k.s (from stream map field "s") holds the input scrambled signature
        -- k.sp (from stream map field "sp") holds a parameter name (normally
        -- "signature" or "sig") to set with the output, descrambled signature
        local descrambler = js_extract( js, "[=%(,&|](...?)%(decodeURIComponent%(.%.s%)%)" )
        if not descrambler then
            vlc.msg.dbg( "Couldn't extract youtube video URL signature descrambling function name" )
            return nil
        end
    
        -- Fetch the code of the descrambler function
        -- Go=function(a){a=a.split("");Fo.sH(a,2);Fo.TU(a,28);Fo.TU(a,44);Fo.TU(a,26);Fo.TU(a,40);Fo.TU(a,64);Fo.TR(a,26);Fo.sH(a,1);return a.join("")};
        local rules = js_extract( js, "^"..descrambler.."=function%([^)]*%){(.-)};" )
        if not rules then
            vlc.msg.dbg( "Couldn't extract youtube video URL signature descrambling rules" )
            return nil
        end
    
        -- Get the name of the helper object providing transformation definitions
        local helper = string.match( rules, ";(..)%...%(" )
        if not helper then
            vlc.msg.dbg( "Couldn't extract youtube video URL signature transformation helper name" )
            return nil
        end
    
        -- Fetch the helper object code
        -- var Fo={TR:function(a){a.reverse()},TU:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c},sH:function(a,b){a.splice(0,b)}};
        local transformations = js_extract( js, "[ ,]"..helper.."={(.-)};" )
        if not transformations then
            vlc.msg.dbg( "Couldn't extract youtube video URL signature transformation code" )
            return nil
        end
    
        -- Parse the helper object to map available transformations
        local trans = {}
        for meth,code in string.gmatch( transformations, "(..):function%([^)]*%){([^}]*)}" ) do
            -- a=a.reverse()
            if string.match( code, "%.reverse%(" ) then
              trans[meth] = "reverse"
    
            -- a.splice(0,b)
            elseif string.match( code, "%.splice%(") then
              trans[meth] = "slice"
    
            -- var c=a[0];a[0]=a[b%a.length];a[b]=c
            elseif string.match( code, "var c=" ) then
              trans[meth] = "swap"
            else
                vlc.msg.warn("Couldn't parse unknown youtube video URL signature transformation")
            end
        end
    
        -- Parse descrambling rules, map them to known transformations
        -- and apply them on the signature
        local missing = false
        for meth,idx in string.gmatch( rules, "..%.(..)%([^,]+,(%d+)%)" ) do
            idx = tonumber( idx )
    
            if trans[meth] == "reverse" then
                sig = string.reverse( sig )
    
            elseif trans[meth] == "slice" then
                sig = string.sub( sig, idx + 1 )
    
            elseif trans[meth] == "swap" then
                if idx > 1 then
                    sig = string.gsub( sig, "^(.)("..string.rep( ".", idx - 1 )..")(.)(.*)$", "%3%2%1%4" )
                elseif idx == 1 then
                    sig = string.gsub( sig, "^(.)(.)", "%2%1" )
                end
            else
                vlc.msg.dbg("Couldn't apply unknown youtube video URL signature transformation")
                missing = true
            end
        end
        if missing then
            vlc.msg.err( "Couldn't process youtube video URL, please check for updates to this script" )
        end
        return sig
    end
    
    -- Parse and assemble video stream URL
    function stream_url( params, js )
        local url = string.match( params, "url=([^&]+)" )
        if not url then
            return nil
        end
        url = vlc.strings.decode_uri( url )
    
        -- Descramble any scrambled signature and append it to URL
        local s = string.match( params, "s=([^&]+)" )
        if s then
            s = vlc.strings.decode_uri( s )
            vlc.msg.dbg( "Found "..string.len( s ).."-character scrambled signature for youtube video URL, attempting to descramble... " )
            local ds = sig_descramble( s, js )
            if not ds then
                vlc.msg.dbg( "Couldn't descramble YouTube video URL signature" )
                vlc.msg.err( "Couldn't process youtube video URL, please check for updates to this script" )
                ds = s
            end
    
            local sp = string.match( params, "sp=([^&]+)" )
            if not sp then
                vlc.msg.warn( "Couldn't extract signature parameters for youtube video URL, guessing" )
                sp = "signature"
            end
            url = url.."&"..sp.."="..vlc.strings.encode_uri_component( ds )
        end
    
        return url
    end
    
    -- Parse and pick our video stream URL (classic parameters, out of use)
    function pick_url( url_map, fmt, js_url )
        for stream in string.gmatch( url_map, "[^,]+" ) do
            local itag = string.match( stream, "itag=(%d+)" )
            if not fmt or not itag or tonumber( itag ) == tonumber( fmt ) then
                return nil -- stream_url( stream, js_url )
            end
        end
        return nil
    end
    
    -- Pick suitable stream among available formats
    function pick_stream( formats, fmt )
        if not formats then
            return nil
        end
    
        -- Remove subobject fields to ease parsing of stream object array
        formats = string.gsub( formats, '"[^"]-":{[^{}]-},?', '' )
    
        if tonumber( fmt ) then
            -- Legacy match from URL parameter
            fmt = tonumber( fmt )
            for stream in string.gmatch( formats, '{(.-)}' ) do
                local itag = tonumber( string.match( stream, '"itag":(%d+)' ) )
                if fmt == itag then
                    return stream
                end
            end
            return nil
        else
            -- Compare the different available formats listed with our
            -- quality targets
            local prefres = vlc.var.inherit( nil, "preferred-resolution" )
            local bestres, pick
            for stream in string.gmatch( formats, '{(.-)}' ) do
                local height = tonumber( string.match( stream, '"height":(%d+)' ) )
    
                -- We have no preference mechanism for audio formats,
                -- so just pick the first one
                if fmt == "audio" and not height then
                    return stream
                end
    
                -- Better than nothing
                if ( not pick and fmt ~= "video" ) or ( height and ( not bestres
                    -- Better quality within limits
                    or ( ( prefres < 0 or height <= prefres ) and height > bestres )
                    -- Lower quality more suited to limits
                    or ( prefres > -1 and bestres > prefres and height < bestres )
                ) ) then
                    bestres = height
                    pick = stream
                end
            end
            return pick
        end
    end
    
    -- Parse and pick our video stream URL (new-style parameters)
    function pick_stream_url( muxed, adaptive, js_url, fmt )
        -- Shared JavaScript resources - lazy initialization
        local js = { url = js_url, stream = nil, lines = {}, i = 0 }
        if not js.url then
            vlc.msg.warn( "Couldn't extract YouTube JavaScript player code URL, descrambling functions unavailable" )
        end
    
        local pick = nil
        if tonumber( fmt ) then
            -- Specific numeric itag, search in both lists
            pick = pick_stream( muxed, fmt )
            if not pick then
                pick = pick_stream( adaptive, fmt )
            end
        elseif ( fmt == "audio" or fmt == "video" ) then
            -- Specifically audio or video only, no fallback
            pick = pick_stream( adaptive, fmt )
        else
            if fmt == "hd" then
                -- Try and leverage full array of adaptive formats
                local audio = pick_stream( adaptive, "audio" )
                local video = pick_stream( adaptive, "video" )
                if audio and video then
                    local audio_url = assemble_stream_url( audio, js )
                    local video_url = assemble_stream_url( video, js )
                    if audio_url and video_url then
                        return video_url, audio_url
                    end
                end
            end
    
            if not pick then
                -- Default or fallback: safe old multiplexed streams,
                -- but reduced to a single, low-definition format
                -- available in some cases
                pick = pick_stream( muxed, fmt )
            end
        end
    
        if not pick then
            return nil
        end
        return assemble_stream_url( pick, js )
    end
    
    -- Parse, descramble and assemble elements of video stream URL
    function assemble_stream_url( pick, js )
        -- 1/ URL signature
        -- Either the "url" or the "signatureCipher" parameter is present,
        -- depending on whether the URL signature is scrambled.
        local url
        local cipher = string.match( pick, '"signatureCipher":"(.-)"' )
            or string.match( pick, '"[a-zA-Z]*[Cc]ipher":"(.-)"' )
        if cipher then
            -- Scrambled signature: some assembly required
            url = stream_url( cipher, js )
        end
        if not url then
            -- Unscrambled signature, already included in ready-to-use URL
            url = string.match( pick, '"url":"(.-)"' )
        end
    
        if not url then
            return nil
        end
    
        -- 2/ Data transfer throttling
        -- The "n" parameter is scrambled too, and needs to be descrambled
        -- and replaced in place, otherwise the data transfer gets throttled
        -- down to between 40 and 80 kB/s, below real-time playability level.
        local n = string.match( url, "[?&]n=([^&]+)" )
        if n then
            n = vlc.strings.decode_uri( n )
            local dn = nil -- n_descramble( n, js )
            if dn then
                url = string.gsub( url, "([?&])n=[^&]+", "%1n="..vlc.strings.encode_uri_component( dn ), 1 )
            else
                vlc.msg.err( "Couldn't descramble YouTube throttling URL parameter: data transfer will get throttled" )
                --vlc.msg.err( "Couldn't process youtube video URL, please check for updates to this script" )
            end
        end
    
        return url
    end
    
    -- Probe function.
    function probe()
        return ( ( vlc.access == "http" or vlc.access == "https" ) and (
                ((
                   string.match( vlc.path, "^www%.youtube%.com/" )
                or string.match( vlc.path, "^music%.youtube%.com/" )
                or string.match( vlc.path, "^gaming%.youtube%.com/" ) -- out of use
                 ) and (
                   string.match( vlc.path, "/watch%?" ) -- the html page
                or string.match( vlc.path, "/live$" ) -- user live stream html page
                or string.match( vlc.path, "/live%?" ) -- user live stream html page
                or string.match( vlc.path, "/shorts/" ) -- YouTube Shorts HTML page
                or string.match( vlc.path, "/get_video_info%?" ) -- info API
                or string.match( vlc.path, "/v/" ) -- video in swf player
                or string.match( vlc.path, "/embed/" ) -- embedded player iframe
                 )) or
                   string.match( vlc.path, "^consent%.youtube%.com/" )
             ) )
    end
    
    -- Parse function.
    function parse()
        if string.match( vlc.path, "^consent%.youtube%.com/" ) then
            -- Cookie consent redirection
            -- Location: https://consent.youtube.com/m?continue=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DXXXXXXXXXXX&gl=FR&m=0&pc=yt&uxe=23983172&hl=fr&src=1
            -- Set-Cookie: CONSENT=PENDING+355; expires=Fri, 01-Jan-2038 00:00:00 GMT; path=/; domain=.youtube.com
            local url = get_url_param( vlc.path, "continue" )
            if not url then
                vlc.msg.err( "Couldn't handle YouTube cookie consent redirection, please check for updates to this script or try disabling HTTP cookie forwarding" )
                return { }
            end
            return { { path = vlc.strings.decode_uri( url ), options = { ":no-http-forward-cookies" } } }
        elseif not string.match( vlc.path, "^www%.youtube%.com/" ) then
            -- Skin subdomain
            return { { path = vlc.access.."://"..string.gsub( vlc.path, "^([^/]*)/", "www.youtube.com/" ) } }
    
        elseif string.match( vlc.path, "/watch%?" )
            or string.match( vlc.path, "/live$" )
            or string.match( vlc.path, "/live%?" )
            or string.match( vlc.path, "/shorts/" )
        then -- This is the HTML page's URL
            local path, path2, title, description, artist, arturl, js_url
    
            -- Retired YouTube API for video format itag parameter,
            -- still supported and extended as youtube.lua API
            -- https://en.wikipedia.org/w/index.php?title=YouTube&oldid=716878321#Quality_and_formats
            local fmt = get_url_param( vlc.path, "fmt" )
    
            while true do
                -- The new HTML code layout has fewer and longer lines; always
                -- use the long line workaround until we get more visibility.
                local line = new_layout and read_long_line() or vlc.readline()
                if not line then break end
    
                -- The next line is the major configuration line that we need.
                -- It is very long so we need this workaround (see #24957).
                if string.match( line, '^ *<div id="player%-api">' ) then
                    line = read_long_line()
                    if not line then break end
                end
    
                if not title then
                    local meta = string.match( line, '<meta property="og:title"( .-)>' )
                    if meta then
                        title = string.match( meta, ' content="(.-)"' )
                        if title then
                            title = vlc.strings.resolve_xml_special_chars( title )
                        end
                    end
                end
    
                if not description then
                    -- FIXME: there is another version of this available,
                    -- without the double JSON string encoding, but we're
                    -- unlikely to access it due to #24957
                    description = string.match( line, '\\"shortDescription\\":\\"(.-[^\\])\\"')
                    if description then
                        -- FIXME: do this properly (see #24958)
                        description = string.gsub( description, '\\(["\\/])', '%1' )
                    else
                        description = string.match( line, '"shortDescription":"(.-[^\\])"')
                    end
                    if description then
                        if string.match( description, '^"' ) then
                            description = ""
                        end
                        -- FIXME: do this properly (see #24958)
                        -- This way of unescaping is technically wrong
                        -- so as little as possible of it should be done
                        description = string.gsub( description, '\\(["\\/])', '%1' )
                        description = string.gsub( description, '\\n', '\n' )
                        description = string.gsub( description, '\\r', '\r' )
                        description = string.gsub( description, "\\u0026", "&" )
                    end
                end
    
                if not arturl then
                    local meta = string.match( line, '<meta property="og:image"( .-)>' )
                    if meta then
                        arturl = string.match( meta, ' content="(.-)"' )
                        if arturl then
                            arturl = vlc.strings.resolve_xml_special_chars( arturl )
                        end
                    end
                end
    
                if not artist then
                    artist = string.match(line, '\\"author\\":\\"(.-)\\"')
                    if artist then
                        -- FIXME: do this properly (see #24958)
                        artist = string.gsub( artist, '\\(["\\/])', '%1' )
                    else
                        artist = string.match( line, '"author":"(.-)"' )
                    end
                    if artist then
                        -- FIXME: do this properly (see #24958)
                        artist = string.gsub( artist, "\\u0026", "&" )
                    end
                end
    
                if not new_layout then
                    if string.match( line, '<script nonce="' ) then
                        vlc.msg.dbg( "Detected new YouTube HTML code layout" )
                        new_layout = true
                    end
                end
    
                -- We need this when parsing the main stream configuration;
                -- it can indeed be found on that same line (among others).
                if not js_url then
                    js_url = string.match( line, '"jsUrl":"(.-)"' )
                        or string.match( line, "\"js\": *\"(.-)\"" )
                    if js_url then
                        js_url = string.gsub( js_url, "\\/", "/" )
                        -- Resolve URL
                        if string.match( js_url, "^/[^/]" ) then
                            local authority = string.match( vlc.path, "^([^/]*)/" )
                            js_url = "//"..authority..js_url
                        end
                        js_url = string.gsub( js_url, "^//", vlc.access.."://" )
                    end
                end
    
                -- JSON parameters, also formerly known as "swfConfig",
                -- "SWF_ARGS", "swfArgs", "PLAYER_CONFIG", "playerConfig",
                -- "ytplayer.config" ...
                if string.match( line, "ytInitialPlayerResponse ?= ?{" )
                    or string.match( line, "ytplayer%.config" ) then
    
                    -- Classic parameters - out of use since early 2020
                    if not fmt then
                        fmt_list = string.match( line, "\"fmt_list\": *\"(.-)\"" )
                        if fmt_list then
                            fmt_list = string.gsub( fmt_list, "\\/", "/" )
                            fmt = get_fmt( fmt_list )
                        end
                    end
    
                    url_map = string.match( line, "\"url_encoded_fmt_stream_map\": *\"(.-)\"" )
                    if url_map then
                        vlc.msg.dbg( "Found classic parameters for youtube video stream, parsing..." )
                        -- FIXME: do this properly (see #24958)
                        url_map = string.gsub( url_map, "\\u0026", "&" )
                        path = pick_url( url_map, fmt, js_url )
                    end
    
                    -- New-style parameters
                    if not path then
                        local stream_map = string.match( line, '\\"formats\\":%[(.-)%]' )
                        if stream_map then
                            -- FIXME: do this properly (see #24958)
                            stream_map = string.gsub( stream_map, '\\(["\\/])', '%1' )
                        else
                            stream_map = string.match( line, '"formats":%[(.-)%]' )
                        end
                        if stream_map then
                            -- FIXME: do this properly (see #24958)
                            stream_map = string.gsub( stream_map, "\\u0026", "&" )
                        end
    
                        local adaptive_map = string.match( line, '"adaptiveFormats":%[(.-)%]' )
                        if adaptive_map then
                            -- FIXME: do this properly (see #24958)
                            adaptive_map = string.gsub( adaptive_map, "\\u0026", "&" )
                        end
    
                        if stream_map or adaptive_map then
                            vlc.msg.dbg( "Found new-style parameters for youtube video stream, parsing..." )
                            path, path2 = pick_stream_url( stream_map, adaptive_map, js_url, fmt )
                        end
                    end
    
                    if not path then
                        -- If this is a live stream, the URL map will be empty
                        -- and we get the URL from this field instead
                        local hlsvp = string.match( line, '\\"hlsManifestUrl\\": *\\"(.-)\\"' )
                            or string.match( line, '"hlsManifestUrl":"(.-)"' )
                        if hlsvp then
                            hlsvp = string.gsub( hlsvp, "\\/", "/" )
                            path = hlsvp
                        end
                    end
                end
            end
    
            if not path then
                vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
                return { }
            end
    
            if not arturl then
                arturl = get_arturl()
            end
    
            local options = { }
            if path2 then
                table.insert( options, ":input-slave="..path2 )
            end
            return { { path = path; name = title; description = description; artist = artist; arturl = arturl; options = options } }
    
        elseif string.match( vlc.path, "/get_video_info%?" ) then
            -- video info API, retired since summer 2021
            -- Replacement Innertube API requires HTTP POST requests
            -- and so remains for now unworkable from lua parser scripts
            -- (see #26185)
    
            local line = vlc.read( 1024*1024 ) -- data is on one line only
            if not line then
                vlc.msg.err( "YouTube API output missing" )
                return { }
            end
    
            local js_url = get_url_param( vlc.path, "jsurl" )
            if js_url then
                js_url= vlc.strings.decode_uri( js_url )
            end
    
            -- Classic parameters - out of use since early 2020
            local fmt = get_url_param( vlc.path, "fmt" )
            if not fmt then
                local fmt_list = string.match( line, "&fmt_list=([^&]*)" )
                if fmt_list then
                    fmt_list = vlc.strings.decode_uri( fmt_list )
                    fmt = get_fmt( fmt_list )
                end
            end
    
            local url_map = string.match( line, "&url_encoded_fmt_stream_map=([^&]*)" )
            if url_map then
                vlc.msg.dbg( "Found classic parameters for youtube video stream, parsing..." )
                url_map = vlc.strings.decode_uri( url_map )
                path = pick_url( url_map, fmt, js_url )
            end
    
            -- New-style parameters
            if not path then
                local stream_map = string.match( line, '%%22formats%%22%%3A%%5B(.-)%%5D' )
                if stream_map then
                    vlc.msg.dbg( "Found new-style parameters for youtube video stream, parsing..." )
                    stream_map = vlc.strings.decode_uri( stream_map )
                    -- FIXME: do this properly (see #24958)
                    stream_map = string.gsub( stream_map, "\\u0026", "&" )
                    path = pick_stream_url( stream_map, nil, js_url, fmt )
                end
            end
    
            if not path then
                -- If this is a live stream, the URL map will be empty
                -- and we get the URL from this field instead
                local hlsvp = string.match( line, "%%22hlsManifestUrl%%22%%3A%%22(.-)%%22" )
                if hlsvp then
                    hlsvp = vlc.strings.decode_uri( hlsvp )
                    path = hlsvp
                end
            end
    
            if not path and get_url_param( vlc.path, "el" ) ~= "detailpage" then
                -- Retry with the other known value for the "el" parameter;
                -- either value has historically been wrong and failed for
                -- some videos but not others.
                local video_id = get_url_param( vlc.path, "video_id" )
                if video_id then
                    path = vlc.access.."://www.youtube.com/get_video_info?video_id="..video_id.."&el=detailpage"..copy_url_param( vlc.path, "fmt" )..copy_url_param( vlc.path, "jsurl" )
                    vlc.msg.warn( "Couldn't extract video URL, retrying with alternate YouTube API parameters" )
                end
            end
    
            if not path then
                vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
                return { }
            end
    
            local title = string.match( line, "%%22title%%22%%3A%%22(.-)%%22" )
            if title then
                title = string.gsub( title, "+", " " )
                title = vlc.strings.decode_uri( title )
                -- FIXME: do this properly (see #24958)
                title = string.gsub( title, "\\u0026", "&" )
            end
            -- FIXME: description gets truncated if it contains a double quote
            local description = string.match( line, "%%22shortDescription%%22%%3A%%22(.-)%%22" )
            if description then
                description = string.gsub( description, "+", " " )
                description = vlc.strings.decode_uri( description )
                -- FIXME: do this properly (see #24958)
                description = string.gsub( description, '\\(["\\/])', '%1' )
                description = string.gsub( description, '\\n', '\n' )
                description = string.gsub( description, '\\r', '\r' )
                description = string.gsub( description, "\\u0026", "&" )
            end
            local artist = string.match( line, "%%22author%%22%%3A%%22(.-)%%22" )
            if artist then
                artist = string.gsub( artist, "+", " " )
                artist = vlc.strings.decode_uri( artist )
                -- FIXME: do this properly (see #24958)
                artist = string.gsub( artist, "\\u0026", "&" )
            end
            local arturl = string.match( line, "%%22playerMicroformatRenderer%%22%%3A%%7B%%22thumbnail%%22%%3A%%7B%%22thumbnails%%22%%3A%%5B%%7B%%22url%%22%%3A%%22(.-)%%22" )
            if arturl then
                arturl = vlc.strings.decode_uri( arturl )
            end
    
            return { { path = path, name = title, description = description, artist = artist, arturl = arturl } }
    
        else -- Other supported URL formats
            local video_id = string.match( vlc.path, "/[^/]+/([^?]*)" )
            if not video_id then
                vlc.msg.err( "Couldn't extract youtube video URL" )
                return { }
            end
            return { { path = vlc.access.."://www.youtube.com/watch?v="..video_id..copy_url_param( vlc.path, "fmt" ) } }
        end
    end
    

    עזרה הדדית - מחשבים וטכנולוגיה

  • בקשת מידע | מכירים את זה שמישהו שולח בעותק גלוי, וכל הטיפשים מתחילים לשלוח הודעות 'נא להסירני'? מה עושים???
    ס סגנון

    שלום וברכה
    מישהו שלח בטעות הודעה בעותק גלוי למאות אנשים, ועכשיו כולם מתחילים להציף את השרשור בהודעות זועמות של 'נא להסיר', במקום לשתוק ולהפסיק את ההטרדה, הם מקפיצים את ההטרדה פי מאה.
    הייתי מאוד רוצה לכתוב להם 'שויטים שבעולם! תפסיקו להטריד את עצמכם!'
    אבל נראה לי שאחת דינו של כל מי שמגיב שם להפוך את המייל שלו לספאם ללא תקנה.
    לכן אני לא מעז.
    פעם חשבתי לנסות לפתוח איזה מייל אקראי רק לצורך זה, ושיחסם.
    אבל לא מצאתי חברה שמאפשרת דבר כזה.
    יש לכם רעיון איך מלמדים תועי רוח בינה?
    אולי לשלוח אחד אחד לכל רשימת התפוצה שם?
    או שנעזוב אותם, שילמדו בדרך הקשה, שהמייל שלהם יוספאם, ופעם הבאה הם ידעו לא להגיב לעותק גלוי...

    עזרה הדדית - מחשבים וטכנולוגיה

  • בקשת מידע | איך עושים שנגן VLC יוכל להזרים סרטים מיוטיוב
    ס סגנון

    @יחצאל באמצעות פנקס רשימות.
    לי הוא עשה קצת בעיות עם השמירה כי הוא רצה שאהיה מנהל.
    בסוף הסתדרתי איכשהו להחליף ולשמור.

    עזרה הדדית - מחשבים וטכנולוגיה

  • בקשת מידע | איך עושים שנגן VLC יוכל להזרים סרטים מיוטיוב
    ס סגנון

    @יחצאל מה שאני עשיתי בשביל לשמור, זה שהעתקתי אותו למקום אחר במחשב,
    שיניתי מה שרציתי,
    מחקתי את הקובץ המקורי, והעתקתי לשם את הקובץ החדש.

    (אגב, אחרי שVLC מנגן יוטיוב, אפשר להוריד את היוטיוב בקלות ע"י "כלים>>פרטי המקודד>>מיקום"
    מעתיקים את הקישור ומדביקים בדפדפן ומגיעים לסרטון עצמו שיש לו כפתור הורדה בצד.

    עזרה הדדית - מחשבים וטכנולוגיה

  • המלצה | תזכורת | תגבו לכם את הקבצים!! הכל!
    ס סגנון

    יש לי כוננים שיש בהם המון חומר, ומעולם לא ישבתי לעשות מיון מה מביניהם מאוד חשוב ומה לא.
    ולכן לא עשיתי גיבוי בכלל. זה נראה לי מוזר לשלם מאות שקלים בשביל המון סרטונים וקליפים שקיבלתי במיילים ואין לי בהם צורך.

    עזרה הדדית - מחשבים וטכנולוגיה

  • בעיה | החלפתי רישיון אופיס והוא נחסם, איך חוזרים לרישיון המקורי?
    ס סגנון

    בסוף הפעלתי דרך חשבון של הבן שלי ממשרד החינוך

    עזרה הדדית - מחשבים וטכנולוגיה

  • בעיה | לחצן האיקס של תכנת 'תמונות' לא עובד
    ס סגנון

    כשאני פותח תמונות בתכנת 'תמונות' האיקס של 'סגור' לא עובד (ה'מזער' ו'שחזר' כן עובדים).
    לעומת זאת כשאני פותח את התכנה בלי להציג תמונה הלחצן איקס כן עובד.
    c55f01d1-0cd9-42d3-874b-e31725d08d41-image.png

    עזרה הדדית - מחשבים וטכנולוגיה

  • בעיה | הורדת מס' קבצים בדרייב-נטפרי
    ס סגנון

    נטפרי כבר סידרו את הבעיה

    עזרה הדדית - מחשבים וטכנולוגיה

  • בעיה | הלחצנים של תכנת 'תמונות' לא עובדים
    ס סגנון

    שלום וברכה,
    הלחצנים העליונים בתכנת תמונות של מייקרוסופט לא עובדים. חוץ ממזער שחזר ואיקס, וערוך.
    כל המסומן באיור הבא לא עובד אצלי.
    79a6e1a0-58d9-4fc6-83ed-b8575dd370ca-image.png
    עשיתי עדכון לפי מה שכתבו לי כאן https://mitmachim.top/topic/72804/בעיה-לחצן-האיקס-של-תכנת-תמונות-לא-עובד?_=1741124312353
    ולא עזר.

    עזרה הדדית - מחשבים וטכנולוגיה
  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.
  • פוסט ראשון
    פוסט אחרון
0
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר