Change youtube video ID without page reloading

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-02 10:34:28

问题


This question is about scripting the main youtube site, client side from javascript.

While it looks easy as a click, I found no way to change the current video by a new non in context video ID without reloading.

This seems to be related with the polymer library in use, with a lot of shadow dom and some special behavior.

Here is the context: I am making for my own use a bookmarklet that load videos from the reddit json api, wich supports CORS calls.

So far so good, I can load many videos, image previews and links into the youtube sidebar, with this simple enough handcrafted script.

Bookmarklet to call the script:

javascript:void%20function(){target=document.getElementsByTagName(%22script%22)[0],inj=document.createElement(%22script%22),inj.src=%22https://webdev23.github.io/reddube/reddube.js%22,target.appendChild(inj)}();

This bookmarklet is loading into the DOM a js file, that is parsing the json api to get what I need.

Here is the content of the called file:

var reds = ["/r/videos","/r/unknownvideos","/r/DeepIntoYouTube","/r/newsreels","/r/fullmoviesonyoutube","/r/SF_Videos","/r/classicfilms","/r/Documentaries","/r/artdocumentaries","/r/ShowsonYT","/r/YTPL","/r/NotTimAndEric","/r/youtubehaiku","/r/PlayItAgainSam","/r/ObscureMedia","/r/360video","/r/AccidentalComedy","/r/amibeingdetained","/r/ArtisanVideos","/r/AwfulCommercials","/r/bestofworldstar","/r/cringe","/r/CommercialCuts","/r/contagiouslaughter","/r/cookingvideos","/r/curiousvideos","/r/deepintoyoutube","/r/documentaries","/r/educativevideos","/r/FastWorkers","/r/fightporn","/r/FuckingWithNature","/r/fullmoviesonyoutube","/r/happycrowds/","/r/idiotsfightingthings","/r/lectures","/r/mealtimevideos","/r/motivationvideos","/r/ObscureMedia","/r/playitagainsam","/r/Prematurecelebration","/r/PublicFreakout","/r/Roadcam","/r/streetfights","/r/sweetjustice","/r/TheWayWeWereOnVideo","/r/trailers","/r/UnexpectedThugLife","/r/videoporn","/r/vids","/r/vines","/r/virtualfreakout","/r/woahtube","/r/listentothis/","/r/Tekno/","/r/reggae/","/r/RootsReggae","r/ska","/r/dub","/r/hip_hop","/r/treemusic/","/r/stonerrock/","/r/frenchrap/","/r/trance/","/r/minimal/"]  
var rview = ["","/new/","/rising/","/controversial/","/top/"]  
related.innerHTML = "<div style='filter: sepia(38%) invert(100%) saturate(100%) brightness(1) grayscale(0%) hue-rotate(360deg) contrast(100%)'><span id='subR' data-ccc='25' style='color:white;background:#141e1b;font-size:1.44em;width:20px'></span><input type='range' value='0' max='64' id ='redR' style='float:right;width:230px' onchange='redList.innerHTML=\"\";redd(this.value)'><br><span onclick='redList.innerHTML=\"\";' style='float:right;margin:3px 0 0 0'><button id='rflt' data-filter='0' onclick='this.dataset.filter=0;redd(redR.value)'>hot</button><button onclick='rflt.dataset.filter=1;redd(redR.value)'>new</button><button onclick='rflt.dataset.filter=2;redd(redR.value)'>rising</button><button onclick='rflt.dataset.filter=3;redd(redR.value)'>controversial</button><button onclick='rflt.dataset.filter=4;redd(redR.value)'>top</button></span><hr /><hr /><hr /><hr /><hr /><tr><br></div><div id='redList'>"

function redd(it){
 console.log(it)    
 console.log(reds[1])

 subR.innerHTML = reds[it]

  xhr = new XMLHttpRequest
  xhr.open("GET","https://www.reddit.com"+reds[it]+rview[rflt.dataset.filter]+".json?limit=200",true)
  xhr.send(null)
  xhr.onreadystatechange = function() {
   if (xhr.readyState === xhr.DONE) {
    if(this.status === 200) {

      vids = JSON.parse(xhr.responseText) 

      cc = subR.dataset.ccc

    for (var j=0;j<=cc;j++){
     try{ 
      var rt = vids['data']['children'][j]['data']['title'],
      rl = vids['data']['children'][j]['data']['url'],
      rp = vids['data']['children'][j]['data']['secure_media']['oembed']['thumbnail_url'],
      rr = vids['data']['children'][j]['data']['permalink']     

      redList.innerHTML += "<td><a href='"+rl+"'><img style='width:150px;height:auto;max-width:120px' src='"+rp+"'></img></a><span style='max-width:68%;float:right;text-align:center;font-size:1.23em'><a class='yt-simple-endpoint style-scope ytd-compact-video-renderer' style='text-decoration:bold;font-size:1.23em;text-align:left;min-width:260px' href='"+rl+"'>"+rt+"</a><a target='blank' style='text-decoration:bold;color:black;float:right' href='https://www.reddit.com"+rr+"'>⮊</a></span></td><br>"
     }catch(e){console.log(e)}

    }   
      }
    }
  }
}

related.innerHTML += "</tr><button onclick='redList.innerHTML=\"\";redd(redR.value)'>Load more</button>"
redd(0)

window.onscroll = function() {
  var d = document.documentElement,
      offset = d.scrollTop + window.innerHeight,
      height = d.offsetHeight

  if (offset >= '2000' && offset <= '2300') {

     subR.dataset.ccc = 25

  }

  if (offset >= '2000' && offset <= '2100') {

     subR.dataset.ccc = 50

  }

  if (offset >= '3400' && offset <= '3500') {

     subR.dataset.ccc = 100


  }
  if (offset >= '5400' && offset <= '5500') {

     subR.dataset.ccc = 150

  }

  if (offset >= '7400' && offset <= '7500') {

     subR.dataset.ccc = 200

  }
}

At this stage, clicking a link is just reloading the page.

I tried many things, changing the content of elements, try to alter the "next" recommended video.

Also creating a link in the DOM, isn't working, it is reloading.

Here is the problem in a simple way:

Let's say you are in this yt page https://www.youtube.com/watch?v=YgGzAKP_HuM

From the console, how to load this non related id -q7ZVXOU3kM into the page, just like a link click on the recommendation sidebar?

The following is NOT working: Visibility monitor is not attached

 xhr = new XMLHttpRequest
 xhr.open("GET","https://www.youtube.com/watch?v=-q7ZVXOU3kM",true)
 xhr.send(null)
 document.body.innerHTML = xhr

18 OF MARCH 2018: END OF BOUNTY: QUESTION UNRESOLVED!!!

This is a fairly complex stuff.

The dom content is constantly changing at every reload, and it include recommended video id into the changing scripts. This id's only are allowed to use the ajax capabilities.

This recommendation are changing at any reload, but they are coming back in loop.

I am building a tool to deeply analyse differences, and i found many interesting things, much more that I was searching.

This topic isn't close!

It's not about the destination, it's about the journey.


回答1:


Despite the videoId being YgGzAKP_HuMif you inspect the <video> you will see something like that:

<video class="video-stream html5-main-video" src="blob:https://www.youtube.com/8e1ef216-1901-ec44-9b76-ea8276e368c6"></video>

You need to find how youtube create their Blob from a videoId and change the src of the player if you want to avoid reloading the page.

But maybe for your project you should think about using the IFrame Player API. It does exactly what you want. And if you want to stay on youtube.com you can replace the youtube original player by an iframe in the DOM.

Good Luck!




回答2:


it appears that there is no (public) api for the player on youtube :/ but there is one for the iframe youtube player - there you can just call

player.loadVideoById("Vw4KVoEVcr0", 0, "default");

for details see https://developers.google.com/youtube/iframe_api_reference#loadVideoById

That is a quick example I found where you see it in action: http://jsfiddle.net/QtBlueWaffle/8bpQ8/1/

If you really want to directly modify youtube you probably have to dig around in the obfuscated code :/ I tried to find it... but it's obfuscated so you can't easily find it. And even if you find it it will be something like _yt_player.h.xx.xy.h(). Also whenever it will be generated new (and maybe even it is even different for countries... ) your code may break.

Also, it appears to have nothing to do with polymer as there is a player element but it does not have a function to change the video. Apparently, it is only to place the player... control still resides within the js function.

I'm sorry to not have any better news - maybe someone else knows more.




回答3:


Trying to find a hidden YouTube API is incredibly difficult and it's likely that the next tweak Google makes to YouTube will break your bookmarklet and you'd be back where you started. I think you should take another route altogether. Google provides an API to create, delete, and otherwise manipulate YouTube playlists here: https://developers.google.com/youtube/v3/docs/playlists.

If you’ve never used YouTube API before, see here: https://developers.google.com/youtube/v3/getting-started

Then, (finally!) you can write some JavaScript that creates YouTube playlists from reddit at your command.



来源:https://stackoverflow.com/questions/49138693/change-youtube-video-id-without-page-reloading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!