您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自分のPC内の動画ファイルと差し替えてニコニコできます。
当前为
// ==UserScript== // @name Niconico My Theater // @namespace knoa.jp // @description 自分のPC内の動画ファイルと差し替えてニコニコできます。 // @include https://www.nicovideo.jp/watch/* // @version 0.1 // @grant none // ==/UserScript== (function(){ const SCRIPTNAME = 'NiconicoMyTheater'; const DEBUG = false;/* [to do] ZenzaWatch対応。 ローディング表示 置き換え完了時に何かリアクションを。 元の動画に戻すボタンで確認してから戻せるように。 ニコニコの時刻表示に時間単位追加 [bug] Firefoxのblob処理が重いのかどうか? */ if(window === top && console.time) console.time(SCRIPTNAME); const SHIFTARROW = 1;// Shift + 左右キーで移動する(秒) let site = { get: { playerOptionButton: () => $('button[data-title="設定"]'), originalVideo: () => $('#VideoPlayer video[src]'), videoStartButton: () => $('.VideoStartButton'), footerContainerLinks: () => $('.FooterContainer-links'), }, }; let originalVideo, replacedVideo; let core = { initialize: function(){ core.addFileButton(); core.linkVideos(); core.listenEvents(); core.addFooter(); core.addStyle(); }, addFileButton: function(){ let playerOptionButton = site.get.playerOptionButton(); if(!playerOptionButton) return setTimeout(core.addFileButton, 1000); let fileButton = createElement(core.html.fileButton()); let input = fileButton.querySelector('input[type="file"]'); fileButton.addEventListener('click', function(e){ input.click(); }); input.addEventListener('change', function(e){ log('changed!'); let object = URL.createObjectURL(input.files[0]); replacedVideo.src = object; replacedVideo.classList.add('loaded'); // オリジナルビデオの状態をコピー replacedVideo.currentTime = originalVideo.currentTime; replacedVideo.playbackRate = originalVideo.playbackRate; replacedVideo.volume = originalVideo.volume; // オリジナルビデオは影の存在となる originalVideo.style.visibility = 'hidden';//displayは上書きされる originalVideo.muted = true; // ローディング表示 // }); playerOptionButton.parentNode.insertBefore(fileButton, playerOptionButton); }, linkVideos: function(){ // リプレイスビデオ要素の準備 originalVideo = site.get.originalVideo(); if(!originalVideo) return setTimeout(core.linkVideos, 1000); replacedVideo = createElement(core.html.replacedVideo()); originalVideo.parentNode.insertBefore(replacedVideo, originalVideo); // 連動 originalVideo.addEventListener('play', function(e){ log('originalVideo: play!'); replacedVideo.currentTime = originalVideo.currentTime; replacedVideo.playbackRate = originalVideo.playbackRate; replacedVideo.play(); }); originalVideo.addEventListener('pause', function(e){ log('originalVideo: pause!'); replacedVideo.currentTime = originalVideo.currentTime; replacedVideo.pause(); }); originalVideo.addEventListener('seeking', function(e){ log('originalVideo: seeking!'); replacedVideo.currentTime = originalVideo.currentTime; }); originalVideo.addEventListener('canplay', function(e){ log('originalVideo: canplay!'); replacedVideo.currentTime = originalVideo.currentTime; }); originalVideo.addEventListener('volumechange', function(e){ replacedVideo.volume = originalVideo.volume; }); // 連動(?) replacedVideo.addEventListener('seeking', function(e){ log('replacedVideo: seeking!'); }); replacedVideo.addEventListener('canplay', function(e){ log('replacedVideo: canplay!'); }); }, listenEvents: function(){ window.addEventListener('keydown', function(e){ switch(true){ case(e.key === 'ArrowLeft' && e.shiftKey): replacedVideo.currentTime = originalVideo.currentTime = originalVideo.currentTime - SHIFTARROW; break; case(e.key === 'ArrowRight' && e.shiftKey): replacedVideo.currentTime = originalVideo.currentTime = originalVideo.currentTime + SHIFTARROW; break; } }, true); }, addFooter: function(){ let footerContainerLinks = site.get.footerContainerLinks(); if(!footerContainerLinks) return setTimeout(core.addFooter, 1000); footerContainerLinks.appendChild(createElement(core.html.footer())); }, addStyle: function(){ let style = createElement(core.html.style()); document.head.appendChild(style); }, html: { fileButton: () => ` <button class="ActionButton ControllerButton FileButton" type="button" data-title="ファイルに差し替える"> <div class="ControllerButton-inner"> <!-- https://www.onlinewebfonts.com/icon/112309 --> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" enable-background="new 0 0 1000 1000" viewBox="0 0 1000 1000" xml:space="preserve"> <metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata> <g><path d="M581.7,10H132.5v980h735V295.8L581.7,10z M785.8,908.3H214.2V91.7h374.5l197.1,197.1V908.3z"></path><path d="M540.8,10v326.7h326.7L540.8,10z"></path><path d="M377.5,418.3V745l285.8-163.3L377.5,418.3z"></path></g> </svg> </div> <input type="file" id="${SCRIPTNAME}-file"> </button> `, replacedVideo: () => ` <video preload="auto" id="${SCRIPTNAME}-replaced" ${DEBUG ? 'controls' : ''}> `, footer: () => ` <li><a href="http://www.onlinewebfonts.com">oNline Web Fonts</a></li> `, style: () => ` <style type="text/css"> input#${SCRIPTNAME}-file{ display: none; } video#${SCRIPTNAME}-replaced{ transition: opacity .5s; opacity: 0; z-index: 100; position: absolute; width: 100%; height: 100%; top: 0px; left: 0px; bottom: 0px; right: 0px; display: block; } video#${SCRIPTNAME}-replaced.loaded{ opacity: 1; } </style> `, }, }; let $ = function(s){return document.querySelector(s)}; let $$ = function(s){return document.querySelectorAll(s)}; let createElement = function(html){ let outer = document.createElement('div'); outer.innerHTML = html; return outer.firstElementChild; }; let log = function(){ if(!DEBUG) return; let l = log.last = log.now || new Date(), n = log.now = new Date(); let stack = new Error().stack, callers = stack.match(/^([^/<]+(?=<?@))/gm) || stack.match(/[^. ]+(?= \(<anonymous)/gm) || []; console.log( SCRIPTNAME + ':', /* 00:00:00.000 */ n.toLocaleTimeString() + '.' + n.getTime().toString().slice(-3), /* +0.000s */ '+' + ((n-l)/1000).toFixed(3) + 's', /* :00 */ ':' + stack.match(/:[0-9]+:[0-9]+/g)[1].split(':')[1],/*LINE*/ /* caller.caller */ (callers[2] ? callers[2] + '() => ' : '') + /* caller */ (callers[1] || '') + '()', ...arguments ); }; core.initialize(); if(window === top && console.timeEnd) console.timeEnd(SCRIPTNAME); })();