123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734 |
- if(window.__videoplayer_enhancer__){
- window.__videoplayer_enhancer__();
- throw '';
- }else{
- window.__videoplayer_enhancer__ = function(){
- /* lib begin */
- function debounce(fn, ms = 0) {
- let timeoutId;
- return function(...args) {
- clearTimeout(timeoutId);
- timeoutId = setTimeout(() => fn.apply(this, args), ms);
- };
- };
- function throttle(fn, wait) {
- let inThrottle, lastFn, lastTime;
- return function(...args) {
- if (!inThrottle) {
- fn.apply(this, args);
- lastTime = Date.now();
- inThrottle = true;
- } else {
- clearTimeout(lastFn);
- lastFn = setTimeout(function() {
- if (Date.now() - lastTime >= wait) {
- fn.apply(this, args);
- lastTime = Date.now();
- }
- }, Math.max(wait - (Date.now() - lastTime), 0));
- }
- };
- };
- function is_same_size_position(ele1, ele2) {
- try {
- return ele1.clientWidth == ele2.clientWidth &&
- ele1.clientHeight == ele2.clientHeight &&
- ele1.scrollHeight == ele2.scrollHeight;
- } catch {
- return false;
- }
- }
- function find_top_wrap_ele(ele) {
- let origE = ele;
- let wrap = ele;
- do {
- ele = ele.parentElement;
- if (is_same_size_position(wrap, ele)) {
- wrap = ele;
- }
- }while (ele.tagName !== 'BODY');
-
- if(wrap == origE) {
- wrap = document.createElement('div');
- origE.parentElement.insertBefore(wrap, origE);
- wrap.append(origE);
- }
- return wrap;
- }
- function fullscreen2Element(ele) {
- if (document.fullscreen) {
- let curFS = document.fullscreenElement;
- if(curFS.tagName === 'VIDEO') {
- document.exitFullscreen();
- }
- }
- }
- function is_parent(ele, parent) {
- while (ele.tagName !== 'BODY' &&
- ele !== parent && ele.parentElement !== parent) {
- ele = ele.parentElement;
- }
- return ele.parentElement === parent;
- }
- function zero_padding(number, length = 2) {
- return Array(Math.max(length - number.toString().length, 0) + 1).join(0) + number;
- }
- function sec2HHMMSS(time, sec_base = 1) {
- const sec = sec_base, min = 60 * sec, hour = 60 * min;
- const h = Math.floor(time / hour);
- const m = Math.floor(time % hour / min);
- const s = Math.floor(time % min / sec);
- let result = zero_padding(m) + ':' + zero_padding(s);
- if (h) {
- return zero_padding(h) + ':' + result;
- } else {
- return result;
- }
- }
- function HHMMSS2sec(time, sec_base = 1) {
- const sec = sec_base, min = 60 * sec, hour = 60 * min;
- const split = time.split(':');
- if (split.length < 3) {
- split.unshift(0);
- }
- const h = split[0];
- const m = split[1];
- const s = split[2];
- return h * hour + m * min + s * sec;
- }
- function get_1cm_pixel_num() {
- const div = document.createElement('div');
- div.style.cssText = ['position: fixed', 'width: 1cm', 'visibility: hidden'].join('; ');
- document.body.append(div);
- const pixel = div.clientWidth;
- div.remove();
- get_1cm_pixel_num = () => pixel;
- return pixel;
- }
- function px2cm(px) {
- return px / get_1cm_pixel_num();
- }
- /* lib end */
- /* add custom event begin */
- function copy(obj) {
- const new_obj = {};
- for (let i in obj) {
- new_obj[i] = obj[i];
- }
- return new_obj;
- }
- function TapEvent(touch_event) {
- return new TouchEvent('tap',
- Object.assign(copy(touch_event),
- { bubbles: true, cancelable: true, composed: true }));
- }
- function DoubleTapEvent(touch_event) {
- return new TouchEvent('doubletap',
- Object.assign(copy(touch_event),
- { bubbles: true, cancelable: true, composed: true }));
- }
- function TouchEvent2MouseEvent(event_type, event) {
- const touch = event.targetTouches && event.targetTouches[0] || {};
- return new MouseEvent(event_type,
- Object.assign({}, copy(event), copy(touch),
- { bubbles: true, cancelable: true, composed: true }));
- }
- function add_tap_event_hook(element) {
- let start_touch, end_touch, end_event = {};
- const start = e => {
- start_touch = end_touch = copy(e.touches[0]);
- end_event = copy(e);
- };
- const move = e => {
- end_touch = copy(e.touches[0]);
- end_event = copy(e);
- };
- const end = e => {
- if (Math.abs(start_touch.clientX - end_touch.clientX) <= 10 &&
- Math.abs(start_touch.clientY - end_touch.clientY) <= 10) {
- e.target.dispatchEvent(new TapEvent(end_event));
- e.preventDefault();
- e.target.dispatchEvent(TouchEvent2MouseEvent('click', end_event));
- }
- };
- element.addEventListener('touchstart', start, true);
- element.addEventListener('touchmove', move, true);
- element.addEventListener('touchend', end, true);
- return function event_clearer() {
- element.removeEventListener('touchstart', start, true);
- element.removeEventListener('touchmove', move, true);
- element.removeEventListener('touchend', end, true);
- };
- }
- function add_doubletap_event_hook(element) {
- let start_time = 0;
- const doubletap_judge = e => {
- if (Date.now() - start_time <= 250) {
- start_time = 0;
- e.target.dispatchEvent(new DoubleTapEvent(e));
- } else {
- start_time = Date.now();
- }
- };
- element.addEventListener('tap', doubletap_judge, true);
- return function event_clearer() {
- element.removeEventListener('tap', doubletap_judge, true);
- };
- }
- /* add custom event end */
- function create_prompt_panel() {
- const prompt_div = document.createElement('div');
- const prompt_symbol_div = document.createElement('div');
- const prompt_time_div = document.createElement('div');
- const prompt_time_begin_span = document.createElement('span');
- const prompt_time_end_span = document.createElement('span');
- prompt_div.append(prompt_symbol_div, prompt_time_div);
- prompt_time_div.append(prompt_time_begin_span, ' / ', prompt_time_end_span);
- prompt_div.style.cssText = `
- width: 10em;
- position: absolute;
- z-index: 99999999;
- left: 50%;
- top: 50%;
- padding: 15px 0px;
- margin: calc(-0.5em - 15px) auto auto -5em;
- background-color: rgba(51, 51, 51, 0.8);
- border-radius: 15px;
- text-align: center;
- font-size: 0.5cm;
- color: white;
- display: none;
- `;
- prompt_time_begin_span.style.color = '#2fb3ff';
- return {
- div: prompt_div,
- symbol: prompt_symbol_div,
- left_time: prompt_time_begin_span,
- right_time: prompt_time_end_span,
- };
- }
- function create_control_panel() {
- const div = document.createElement('div');
- const content_divs = Array(5).fill().map(() => document.createElement('div'));
- div.append.apply(div, content_divs);
- div.style.cssText = `
- width: 50%;
- height: 100%;
- margin: 0;
- padding: 0;
- position: absolute;
- z-index: 9999999999;
- top: 0;
- left: 30%;
- background-color: rgba(51, 51, 51, 0.8);
- color: white;
- box-sizing: border-box;
- display: none;
- justify-content: center;
- align-items: center;
- font-size: 1cm;
- pointer-events: auto;
- `;
- return {
- display() {
- div.style.display = 'flex';
- },
- hidden() {
- div.style.display = 'none';
- },
- toggle() {
- if (div.style.display === 'flex') {
- this.hidden();
- } else {
- this.display();
- }
- },
- div,
- content_divs,
- };
- }
- const get_video_touch_hook = (video, e) => {
- let top_wrap = find_top_wrap_ele(video);
- if (top_wrap === video) {
- top_wrap = document.createElement('div');
- video.parentElement.insertBefore(top_wrap, video);
- top_wrap.append(video);
- }
- const event_clearer = [add_tap_event_hook, add_doubletap_event_hook].map(x => x(top_wrap));
- const hook_fn = {
- start: [],
- move: [],
- end: [],
- };
- let start_x, start_time;
- const touch_start = e => {
- start_x = e.touches[0].screenX;
- start_time = video.currentTime;
-
- hook_fn.start.forEach(fn => fn(e, start_time));
- //window.playbackRate = video.playbackRate;
- //video.playbackRate = 4.0;
- };
- if (e) {
- setTimeout(touch_start, 0, e);
- }
- const touch_move = e => {
- const end_x = e.touches[0].screenX;
- const x_distance_px = end_x - start_x;
- const time_length = px2cm(x_distance_px) * (this.sec_1cm || 1);
- hook_fn.move.forEach(fn => fn(e, start_time, x_distance_px, time_length));
- fullscreen2Element(top_wrap);
- };
- const touch_end = e => {
- hook_fn.end.forEach(fn => fn(e));
- /*
- video.playbackRate = window.playbackRate;
- const end_x = e.changedTouches[0].pageX;
- if(!(end_x - start_x === 0 ))
- fullscreen2Element(top_wrap);
- */
- };
- top_wrap.addEventListener('touchstart', touch_start, { passive: false });
- top_wrap.addEventListener('touchmove', touch_move, { passive: false });
- top_wrap.addEventListener('touchend', touch_end, { passive: false });
- const remove_hook = () => {
- top_wrap.removeEventListener('touchstart', touch_start);
- top_wrap.removeEventListener('touchmove', touch_move);
- top_wrap.removeEventListener('touchend', touch_end);
- };
- return { video, hook_fn, wrap: top_wrap, event_clearer: event_clearer.concat(remove_hook) };
- };
- const hook_video_move = hook => {
- const {video, hook_fn} = hook;
- hook_fn.start.push(() => {
- paused = video.paused;
- });
- let playing;
- const pause = () => {
- if (!video.paused) {
- video.pause();
- playing = true;
- }
- };
- const play = debounce(() => {
- if (playing) {
- video.play();
- playing = false;
- }
- }, 100);
- hook_fn.move.push((e, start_time, x_distance_px, time_length) => {
- pause();
- video.currentTime = Math.max(Math.min(start_time + time_length,
- video.duration),
- 0);
- play();
- });
- };
- const hook_video_time_change = hook => {
- const {video, hook_fn, event_clearer} = hook;
- const top_wrap = find_top_wrap_ele(video);
- const video_prompt = create_prompt_panel();
- top_wrap.append(video_prompt.div);
- event_clearer.push(() => video_prompt.div.remove());
- hook_fn.start.push(() => {
- video_prompt.right_time.innerText = sec2HHMMSS(video.duration);
- });
- hook_fn.move.push((e, start_time, x_distance_px, time_length) => {
- video_prompt.div.style.display = 'block';
- time_length = video.currentTime - start_time;
- video_prompt.symbol.innerText = time_length < 0 ? '-' : '+';
- video_prompt.symbol.innerText += sec2HHMMSS(Math.abs(time_length));
- video_prompt.left_time.innerText = sec2HHMMSS(video.currentTime);
- });
- hook_fn.end.push(() => {
- video_prompt.div.style.display = 'none';
- });
- };
- const hook_video_control = hook => {
- const {video, hook_fn, event_clearer} = hook;
- const top_wrap = find_top_wrap_ele(video);
- const wrap = document.createElement('div');
- const paddle_div = document.createElement('div');
- const speed_div = document.createElement('div');
- const jump_div = document.createElement('div');
- const skip_div = document.createElement('div');
- const fullscreen_div = document.createElement('div');
- const control = create_control_panel();
- top_wrap.append(wrap);
- const buttons = [paddle_div, speed_div, jump_div, skip_div, fullscreen_div];
- wrap.append.apply(wrap, buttons);
- wrap.append(control.div);
- wrap.style.cssText = `
- width: 100%;
- height: 100%;
- position: absolute;
- top: 0px;
- left: 0px;
- pointer-events: none;
- z-index: 9999999999;
- display: none;
- `;
- const update_wrap_size = () => {
- wrap.style.fontSize = `${Math.min(video.clientHeight, video.clientWidth) / buttons.length / 4}px`;
- };
- update_wrap_size();
- buttons.forEach(div => div.style.cssText =
- `
- width: 3em;
- height: 3em;
- line-height: 3em;
- text-align: center;
- border: solid white;
- border-radius: 100%;
- color: white;
- pointer-events: auto;
- `);
- paddle_div.style.pointerEvents = 'none';
- paddle_div.style.visibility = 'hidden';
- const skip_video = throttle(e => {
- video.currentTime = video.duration;
- }, 500);
- const toggle_play_state = throttle(e => {
- if (video.paused) {
- video.play();
- } else {
- video.pause();
- }
- }, 500);
- const toggle_fullscreen = throttle(e => {
- if (document.fullscreen) {
- document.exitFullscreen();
- } else {
- top_wrap.requestFullscreen();
- }
- }, 500);
- const update_button = () => {
- speed_div.innerText = video.playbackRate + 'x';
- jump_div.innerText = sec2HHMMSS(video.currentTime);
- };
- const hidden_wrap = () => {
- control.hidden();
- wrap.style.display = 'none';
- wrap.style.pointerEvents = 'none';
- };
- const hidden_wrap_delay = debounce(hidden_wrap, 3000);
- const display_wrap = throttle((e) => {
- update_wrap_size();
- wrap.style.display = 'block';
- update_button();
- hidden_wrap_delay();
- }, 1000);
- const prevent_event = e => {
- if (e.cancelable) {
- e.preventDefault();
- }
- e.stopImmediatePropagation();
- };
- skip_div.innerText = 'skip';
- fullscreen_div.innerText = 'FS';
- skip_div.addEventListener('tap', skip_video);
- fullscreen_div.addEventListener('tap', toggle_fullscreen);
- wrap.addEventListener('touchend', prevent_event);
- wrap.addEventListener('touchmove', e => {
- prevent_event(e);
- update_button();
- hidden_wrap_delay();
- });
- top_wrap.addEventListener('tap', display_wrap);
- top_wrap.addEventListener('doubletap', toggle_play_state);
- event_clearer.push(() => {
- top_wrap.removeEventListener('tap', display_wrap);
- top_wrap.removeEventListener('doubletap', toggle_play_state);
- wrap.remove();
- });
- function speed_activate() {
- video.playbackRate = parseFloat(control.div.innerText.replace(/[\r\n]+/g, ''));
- update_button();
- hidden_wrap();
- }
- function jump_activate() {
- video.currentTime = HHMMSS2sec(control.div.innerText.replace(/[\r\n]+/g, ''));
- update_button();
- hidden_wrap();
- }
- function clear_content() {
- control.content_divs.forEach(div => div.innerHTML = '');
- }
- const set_content_tap_fn = (() => {
- let bind_fn = [];
- return fn => {
- bind_fn.forEach(([div, fn]) => div.removeEventListener('tap', fn));
- bind_fn = [];
- control.content_divs.forEach(div => {
- bind_fn.push([div, fn]);
- div.addEventListener('tap', fn);
- });
- };
- })();
- let state = [];
- function set_state() {
- control.content_divs.forEach((div, i) => state[i] = div.innerText);
- }
- let start_y, modifier;
- const start = e => {
- start_y = e.touches[0].screenY;
- set_state();
- };
- const move = e => {
- const end_y = e.touches[0].screenY;
- const y_distance_px = start_y - end_y;
- const increase = Math.floor(px2cm(y_distance_px) * (this.increase_1cm || 1));
- const idx = Array.from(e.target.parentElement.children).indexOf(e.target);
- if (modifier[idx]) {
- modifier[idx](increase);
- }
- };
- const increase_helper = (state_idx, increase,
- limit, pre_ele_modifier, wrap = x => x) => {
- const v = parseFloat(state[state_idx]) + increase;
- if (limit !== undefined) {
- if (pre_ele_modifier) {
- if (v >= limit) {
- pre_ele_modifier(Math.floor(v / limit));
- control.content_divs[state_idx].innerText = wrap(v % limit);
- } else if (v < 0) {
- pre_ele_modifier(-1);
- control.content_divs[state_idx].innerText = wrap(limit + v);
- } else {
- control.content_divs[state_idx].innerText = wrap(v);
- }
- } else {
- control.content_divs[state_idx].innerText =
- wrap(Math.min(Math.max(v, 0), limit));
- }
- } else {
- control.content_divs[state_idx].innerText = wrap(v);
- }
- };
- const speed_modifier = [];
- speed_modifier[0] = (increase) => {
- increase_helper(0, increase);
- };
- speed_modifier[2] = (increase) => {
- increase_helper(2, increase, 10, speed_modifier[0]);
- };
- speed_modifier[3] = (increase) => {
- increase_helper(3, increase, 10, speed_modifier[2]);
- };
- const jump_modifier = [];
- jump_modifier[0] = (increase) => {
- increase_helper(0, increase, undefined, undefined, zero_padding);
- };
- jump_modifier[2] = (increase) => {
- increase_helper(2, increase, 60, jump_modifier[0], zero_padding);
- };
- jump_modifier[4] = (increase) => {
- increase_helper(4, increase, 60, jump_modifier[2], zero_padding);
- };
- speed_div.addEventListener('tap', throttle(e => {
- e.stopImmediatePropagation();
- clear_content();
- if(window.playbackRate>=4.0) window.playbackRate=0.5;
- else if(window.playbackRate<1.0) window.playbackRate=1.0;
- else if(window.playbackRate<1.5) window.playbackRate=1.5;
- else if(window.playbackRate>=2.0) window.playbackRate=4;
- else window.playbackRate = 2.0;
-
- const split = window.playbackRate.toString().split('.');
- control.content_divs[0].innerText = split[0];
- control.content_divs[1].innerText = '.';
- control.content_divs[2].innerText = (split[1] || '00').split('')[0] || 0;
- control.content_divs[3].innerText = (split[1] || '00').split('')[1] || 0;
- control.content_divs[4].innerText = 'x';
- modifier = speed_modifier;
- set_content_tap_fn(speed_activate);
- control.display();
- wrap.style.pointerEvents = 'auto';
- }, 500));
- jump_div.addEventListener('tap', throttle(e => {
- e.stopImmediatePropagation();
- clear_content();
-
- if(control.div.style.display === 'none'||!window.playbackPos)
- window.playbackPos = video.currentTime;
- window.playbackPos += 180;
-
- const time = sec2HHMMSS(window.playbackPos);
- const split = time.split(':');
- if (split.length < 3) {
- split.unshift('00');
- }
- control.content_divs[0].innerText = split[0];
- control.content_divs[1].innerText = ':';
- control.content_divs[2].innerText = split[1];
- control.content_divs[3].innerText = ':';
- control.content_divs[4].innerText = split[2];
- modifier = jump_modifier;
- set_content_tap_fn(jump_activate);
- control.display();
- wrap.style.pointerEvents = 'auto';
- }, 500));
- control.content_divs.forEach(div => {
- div.addEventListener('touchstart', start, { passive: false });
- div.addEventListener('touchmove', move, { passive: false });
- });
- };
- function find_hook(video) {
- window.__hook_video__ = window.__hook_video__ || [];
- const exist_video = window.__hook_video__.find(v => v.video === video);
- return exist_video;
- }
- function register_hook(hook) {
- if (!find_hook(hook.video)) {
- window.__hook_video__.push(hook);
- return hook;
- }
- }
- const hook_video = (video) => {
- const exist_video = find_hook(video);
- if (video.clientWidth && video.clientHeight &&
- (!exist_video || is_parent(exist_video.wrap, find_top_wrap_ele(video)))) {
- const hook = get_video_touch_hook(video);
- hook_video_move(hook);
- hook_video_time_change(hook);
- hook_video_control(hook);
- if (exist_video) {
- exist_video.event_clearer.forEach(x => x());
- Object.assign(exist_video, hook);
- console.log('video-improve: reloaded for ', video, ', wrapped by ', find_top_wrap_ele(video));
- } else {
- register_hook(hook);
- console.log('video-improve: loaded for ', video, ', wrapped by ', find_top_wrap_ele(video));
- }
- }
- };
- let videos;
- if (document.fullscreen) {
- videos = document.fullscreenElement.querySelectorAll('video');
- }else {
- function get_frames(window) {
- const frames = [window];
- for (let i = 0; i < window.frames.length; i++) {
- try {
- window.frames[i].document;
- } catch {
- continue;
- }
- frames.push(...get_frames(window.frames[i]))
- }
- return frames;
- }
- function flatten(array) {
- if (!Array.isArray(array)) {
- return [array];
- } else if (array.length == 0) {
- return [];
- } else {
- return flatten(array[0]).concat(flatten(array.slice(1)));
- }
- }
- function get_videos() {
- const frames = get_frames(window);
- const frame_video = frame => Array.from(frame.document.querySelectorAll('video'));
- const shadow = frame => Array.from(frame.document.querySelectorAll("shadow-output"));
- const shadow_video = shadow => Array.from(shadow.shadowRoot.querySelectorAll("video"));
- return flatten(frames.map(frame_video)
- .concat(frames.map(f => shadow(f).map(shadow_video))));
- }
- videos = get_videos();
- }
- videos.forEach(hook_video);
- };
- }
- window.__videoplayer_enhancer__();
|