问题
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_HuM
if 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