דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • 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

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
  1. דף הבית
  2. מחשבים וטכנולוגיה
  3. עזרה הדדית - מחשבים וטכנולוגיה
  4. בקשת מידע | איך עושים שנגן VLC יוכל להזרים סרטים מיוטיוב

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

מתוזמן נעוץ נעול הועבר עזרה הדדית - מחשבים וטכנולוגיה
8 פוסטים 3 כותבים 244 צפיות 2 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • ס מנותק
    ס מנותק
    סגנון
    כתב ב נערך לאחרונה על ידי
    #1

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

    1 תגובה 1 תגובה אחרונה
    0
    • ס סגנון

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

      1 מנותק
      1 מנותק
      106
      כתב ב נערך לאחרונה על ידי 106
      #2

      @סגנון
      http://he.wondershare.com/vlc/how-to-play-youtube-videos-in-vlc-media-player.html

      ס תגובה 1 תגובה אחרונה
      0
      • 1 106

        @סגנון
        http://he.wondershare.com/vlc/how-to-play-youtube-videos-in-vlc-media-player.html

        ס מנותק
        ס מנותק
        סגנון
        כתב ב נערך לאחרונה על ידי
        #3

        @106 שם זה ההסבר הבסיסי איך מפעילים תזרים רשת, אצלי התזרים רשת לא עובד עד שיעשו איזה פעולה, לא מצאתי שם הסבר איך.
        בתודה מראש

        תגובה 1 תגובה אחרונה
        0
        • ס מנותק
          ס מנותק
          סגנון
          כתב ב נערך לאחרונה על ידי סגנון
          #4

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

          כאן:
          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
          

          תגובה 1 תגובה אחרונה
          3
          • י מנותק
            י מנותק
            יחצאל
            כתב ב נערך לאחרונה על ידי
            #5

            @סגנון איך מחליפים את התוכן, כלומר איך פותחים את הקובץ ההוא?

            ס תגובה 1 תגובה אחרונה
            0
            • י יחצאל

              @סגנון איך מחליפים את התוכן, כלומר איך פותחים את הקובץ ההוא?

              ס מנותק
              ס מנותק
              סגנון
              כתב ב נערך לאחרונה על ידי
              #6

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

              י תגובה 1 תגובה אחרונה
              1
              • ס סגנון

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

                י מנותק
                י מנותק
                יחצאל
                כתב ב נערך לאחרונה על ידי
                #7

                @סגנון גם לי הוא לא נותן לשמור, אבל אני המנהל אז למה אני לא יכול לשמור?

                ס תגובה 1 תגובה אחרונה
                0
                • י יחצאל

                  @סגנון גם לי הוא לא נותן לשמור, אבל אני המנהל אז למה אני לא יכול לשמור?

                  ס מנותק
                  ס מנותק
                  סגנון
                  כתב ב נערך לאחרונה על ידי
                  #8

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

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

                  תגובה 1 תגובה אחרונה
                  1

                  • התחברות

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

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