YouTube 多视图

多视图视频和流媒体

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         YouTube multi-view
// @name:en      YouTube multi-view
// @name:ja      YouTube 複窓視聴
// @name:zh-cn      YouTube 多视图
// @namespace    https://www.youtube.com/
// @version      2024-07-20
// @description       multi-view video and streaming
// @description:en    multi-view video and streaming
// @description:ja    生放送や動画を複窓で見れます
// @description:zh-cn 多视图视频和流媒体
// @author       ぐらんぴ
// @match        https://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// @require      https://greasyfork.org/scripts/433051-trusted-types-helper/code/Trusted-Types%20Helper.js
// @license      MIT
// ==/UserScript==

divide = 2

let addBtn = setInterval(()=>{
    if(document.querySelectorAll("#end > div").length !== 2){
        clearInterval(addBtn)
    }else{
        let btns = document.querySelector("#buttons"),
            div = document.createElement('div')
        div.innerHTML = `<button style="color: #ff00dd; position: relative; background: transparent; border: none; outline: none; box-shadow: none; cursor: pointer;"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path fill-rule="evenodd" clip-rule="evenodd" d="M11 17H4C2.34315 17 1 15.6569 1 14V6C1 4.34315 2.34315 3 4 3H20C21.6569 3 23 4.34315 23 6V14C23 15.6569 21.6569 17 20 17H13V19H16C16.5523 19 17 19.4477 17 20C17 20.5523 16.5523 21 16 21H8C7.44772 21 7 20.5523 7 20C7 19.4477 7.44772 19 8 19H11V17ZM4 5H20C20.5523 5 21 5.44772 21 6V14C21 14.5523 20.5523 15 20 15H4C3.44772 15 3 14.5523 3 14V6C3 5.44772 3.44772 5 4 5Z"
        fill="currentColor" /></svg></button>`
        btns.before(div)

        let div2 = document.createElement('div')
        div2.innerHTML = `<input type="text" placeholder="URL" style="position: absolute; display: flex; width: 500px; right: 10px; top: 50px;" input>
        <button class="add" style="position: absolute; display: flex; right: 10px; top: 50px;" id='submit'>add</button>
        <button class="switch" style="position: absolute; display: flex; width: 54px; right: 516px; top: 50px;" id='submit'>switch</button>`
        div.appendChild(div2)

        let hideDiv2 = document.querySelector("#end > div:nth-child(2) > div")
        hideDiv2.style.display = 'none'
        document.querySelector("#end > div:nth-child(2) > button").addEventListener('click', ()=>{
            let del = document.querySelectorAll(".del")
            if(hideDiv2.style.display == 'none'){
                hideDiv2.style.display = ''
                del.forEach(elm => {
                    elm.style.display = "";
                })
            }else{
                hideDiv2.style.display = 'none'
                del.forEach(elm => {
                    elm.style.display = "none";
                })
            }
        });
        a()
    }
},1000)
function a(){
    document.querySelector(".add").onclick =()=>{
        if(location.href.match('/watch')){// /watch
            parent = document.querySelector("ytd-watch-flexy") //document.querySelector("ytd-watch-grid")
        }else if(location.href.match('/results')){// /results
            parent = document.querySelector("ytd-search")
        }else{// /home, /subscriptions, /you
            let parents = document.querySelectorAll("ytd-browse")
            for(let i = 0; i < parents.length; i++){
                if(parents[i].getAttribute('role') !== null){
                    parent = parents[i]
                }
            }
        }
        let ytd = document.createElement('div')
        ytd.innerHTML = `
            <div class="area" style="display: none;">
                <div class="content_class" style="display: flex; flex-wrap: wrap;"></div>
            </div>`
        parent.before(ytd)
        if(location.href.match('/watch')){
            Vwidth = (document.querySelector("#masthead").clientWidth-(document.querySelector("yt-icon > span > div > svg").width.animVal.value*3))/2-1 // document.querySelector("#icon > yt-icon-shape > icon-shape > div > svg").width.animVal.value
            console.log(Vwidth)
        }else{
            Vwidth = document.querySelector("#page-manager").clientWidth / divide -1
            console.log(Vwidth)
        }
        Vval = document.querySelector("#end > div:nth-child(2) > div > input[type=text]").value
        if(Vval.match('&')){
            Vsrc = Vval.substring(0, Vval.indexOf("&")).replace("watch?v=", "embed/")
        }else{
            Vsrc = Vval.replace("watch?v=", "embed/")
        }
        let divWatch = document.createElement('div')
        divWatch.innerHTML = `
        <iframe width="${Vwidth}" height="${Math.floor(Vwidth/1.77)}" src="${Vsrc}"
        title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture;
        web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
        <div style="text-align: center;">
        <button class="del" style="position: absolute;" id='submit'>delete</button>
        </div>`
        divWatch.addEventListener('click', (e)=>{
            //console.log(e.target.closest('div').parentNode);
            e.target.closest('div').parentNode.remove()
        });
        document.querySelector(".content_class").appendChild(divWatch)
    }
    document.querySelector(".switch").onclick =()=>{
        if(location.href.match('/watch')){// /watch
            parent = document.querySelector("ytd-watch-flexy")//document.querySelector("ytd-watch-grid")
        }else if(location.href.match('/results')){// /results
            parent = document.querySelector("ytd-search")
        }else{// /home, /subscriptions, /you
            let parents = document.querySelectorAll("ytd-browse")
            for(let i = 0; i < parents.length; i++){
                if(parents[i].getAttribute('role') !== null){
                    parent = parents[i]
                }
            }
        }
        if(parent.style.display == ""){
            parent.style.display = 'none'
            if(document.querySelector(".area") !== null){
                document.querySelector(".area").style.display = ''
            }
        }else{
            parent.style.display = ''
            if(document.querySelector(".area") !== null){
                document.querySelector(".area").style.display = 'none'
            }
        }
    }
}
var oldHref = window.location.href;
var observer = new MutationObserver(()=>{
    if(oldHref != window.location.href){
        oldHref = window.location.href;
        var currHref = window.location.href;
        a()
        if(document.querySelector(".area") !== null && location.href.match('/results')){
            (async () => {
                await new Promise(resolve => setTimeout(resolve, 800)); //Without this code, display = 'none' is unstable.
                document.querySelector("ytd-search").style.display = ''
                document.querySelector(".area").style.display = 'none'
                console.log('async')
            })();
            }else if(document.querySelector(".area") !== null){
                (async () => {
                    await new Promise(resolve => setTimeout(resolve, 800));
                    let parents = document.querySelectorAll("ytd-browse")
                    for(let i = 0; i < parents.length; i++){
                        if(parents[i].getAttribute('role') !== null){
                            if(parents[i].style.display !== 'none' || document.querySelectorAll(".area") !== null){
                                parents[i].style.display = ''
                                document.querySelector(".area").style.display = 'none'
                            }
                        }
                    }
                })();
                }

    }
})
observer.observe(document.body, {childList: true,
                                 subtree: true,
                                });