2022-03-30 12:32:08 +00:00
< template >
2022-05-29 18:13:09 +00:00
<!-- // TODO: down: () => minimize, -->
2022-05-28 01:36:26 +00:00
< div
ref = "vidcontainer"
2022-06-21 23:20:05 +00:00
class = "d-flex flex-column black"
2022-05-28 01:36:26 +00:00
style = "position: relative"
2022-06-21 23:20:05 +00:00
: style = " {
height : isFullscreen ? '100vh' : 'auto' ,
maxHeight : isFullscreen ? '' : '50vh' ,
borderRadius :
$store . state . tweaks . roundWatch && ! isFullscreen
? ` ${ $store . state . tweaks . roundTweak / 3 } rem ${
$store . state . tweaks . roundTweak / 3
} rem 0 rem 0 rem ! important `
: '0' ,
} "
2022-05-28 01:36:26 +00:00
>
2022-04-29 01:44:37 +00:00
< video
ref = "player"
2022-06-24 04:26:44 +00:00
v - touch = " {
up : ( ) => {
if ( ! isFullscreen ) fullscreenHandler ( true ) ;
2022-07-20 03:20:39 +00:00
else if ( verticalFullscreen ) shortNext ( ) ;
2022-06-24 04:26:44 +00:00
} ,
down : ( ) => {
if ( isFullscreen ) fullscreenHandler ( true ) ;
} ,
} "
mediagroup = "vuetubecute"
2022-04-29 01:44:37 +00:00
autoplay
width = "100%"
2022-05-28 01:36:26 +00:00
: src = "vidSrc"
2022-06-09 05:36:01 +00:00
: height = "isFullscreen ? '100%' : 'auto'"
2022-07-20 03:20:39 +00:00
style = "transition: filter 0.15s ease-in-out, transform 0.15s linear"
: class = "
2022-07-29 04:44:26 +00:00
controls ||
seeking ||
skipping ||
( $store . state . player . preload && buffered < 100 )
? verticalFullscreen &&
! ( $store . state . player . preload && buffered < 100 )
2022-07-20 03:20:39 +00:00
? 'dim-ish'
: 'dim'
: ''
"
2022-06-09 05:36:01 +00:00
: style = " {
2022-07-20 03:20:39 +00:00
transform : shortTransition ? 'translateY(-100%)' : '' ,
2022-06-09 05:36:01 +00:00
objectFit : contain ? 'contain' : 'cover' ,
2022-06-21 23:20:05 +00:00
maxHeight : isFullscreen ? '' : '50vh' ,
2022-06-09 05:36:01 +00:00
borderRadius :
$store . state . tweaks . roundWatch && ! isFullscreen
2022-06-21 23:20:05 +00:00
? ` ${ $store . state . tweaks . roundTweak / 3 } rem ${
$store . state . tweaks . roundTweak / 3
} rem 0 rem 0 rem ! important `
2022-06-09 05:36:01 +00:00
: '0' ,
} "
2022-06-21 23:20:05 +00:00
: poster = "$youtube.getThumbnail($route.query.v, 'max', [])"
2022-06-10 02:34:13 +00:00
@ loadedmetadata = "checkDimensions()"
2022-06-21 23:20:05 +00:00
@ click = "controlsHandler()"
2022-04-29 01:44:37 +00:00
/ >
2022-06-24 04:26:44 +00:00
< audio ref = "audio" mediagroup = "vuetubecute" :src = "audSrc" / >
2022-05-28 01:36:26 +00:00
2022-06-09 01:02:16 +00:00
<!-- // TODO: merge the bottom 2 into 1 reusable component -->
2022-05-29 23:41:42 +00:00
< v-btn
2022-06-24 04:26:44 +00:00
v - touch = " {
up : ( ) => {
if ( ! isFullscreen ) fullscreenHandler ( true ) ;
2022-07-20 03:20:39 +00:00
else if ( verticalFullscreen ) shortNext ( ) ;
2022-06-24 04:26:44 +00:00
} ,
down : ( ) => {
if ( isFullscreen ) fullscreenHandler ( true ) ;
} ,
2022-06-27 21:12:32 +00:00
right : ( ) => ( contain = true ) ,
left : ( ) => ( contain = false ) ,
2022-06-24 04:26:44 +00:00
} "
2022-05-29 17:08:21 +00:00
text
tile
2022-06-09 01:02:16 +00:00
color = "white"
: class = "skipping == -10 ? '' : 'invisible'"
style = "
top : 0 ;
left : 0 ;
width : 50 % ;
height : 100 % ;
position : absolute ;
transition : opacity 0.15 s ;
border - radius : 0 100 vh 100 vh 0 ;
2022-06-09 01:48:33 +00:00
text - transform : none ;
font - size : 0.5 rem ;
2022-06-09 01:02:16 +00:00
"
2022-06-09 05:36:01 +00:00
@ click = "controlsHandler()"
@ dblclick = "skipHandler(-10)"
2022-06-09 01:02:16 +00:00
>
< v-icon > mdi - rewind < / v-icon >
2022-06-09 01:48:33 +00:00
<!-- { { skipping } } seconds -- >
2022-06-09 01:02:16 +00:00
< / v-btn >
2022-05-28 01:36:26 +00:00
< v-btn
2022-06-24 04:26:44 +00:00
v - touch = " {
up : ( ) => {
if ( ! isFullscreen ) fullscreenHandler ( true ) ;
2022-07-20 03:20:39 +00:00
else if ( verticalFullscreen ) shortNext ( ) ;
2022-06-24 04:26:44 +00:00
} ,
down : ( ) => {
if ( isFullscreen ) fullscreenHandler ( true ) ;
} ,
2022-06-27 21:12:32 +00:00
right : ( ) => ( contain = false ) ,
left : ( ) => ( contain = true ) ,
2022-06-24 04:26:44 +00:00
} "
2022-05-28 01:36:26 +00:00
text
tile
2022-06-09 01:02:16 +00:00
color = "white"
: class = "skipping == 10 ? '' : 'invisible'"
style = "
top : 0 ;
left : 50 % ;
width : 50 % ;
height : 100 % ;
position : absolute ;
transition : opacity 0.15 s ;
border - radius : 100 vh 0 0 100 vh ;
2022-06-09 01:48:33 +00:00
text - transform : none ;
font - size : 0.5 rem ;
2022-06-09 01:02:16 +00:00
"
2022-06-09 05:36:01 +00:00
@ click = "controlsHandler()"
@ dblclick = "skipHandler(10)"
2022-06-09 01:02:16 +00:00
>
< v-icon > mdi - fast - forward < / v-icon >
2022-06-09 01:48:33 +00:00
<!-- { { skipping } } seconds ] -- >
2022-06-09 01:02:16 +00:00
< / v-btn >
< div
v - if = "seeking"
2022-06-09 01:17:42 +00:00
class = "d-flex justify-center"
style = "width: 100%; top: 0.5rem; position: absolute; font-size: 0.66rem"
2022-06-09 01:02:16 +00:00
>
2022-06-09 01:17:42 +00:00
< v-icon small class = "pr-2" > mdi - rewind < / v-icon >
2022-06-09 14:22:55 +00:00
Double tap left or right to skip 10 seconds
2022-06-09 01:17:42 +00:00
< v-icon small class = "pl-2" > mdi - fast - forward < / v-icon >
2022-06-09 01:02:16 +00:00
< / div >
2022-05-28 01:36:26 +00:00
2022-06-08 19:24:47 +00:00
<!-- controls container -- >
2022-05-28 01:36:26 +00:00
< div
2022-07-29 04:44:26 +00:00
v - if = "$refs.player && $refs.player.currentSrc"
2022-05-28 01:36:26 +00:00
style = "transition: opacity 0.15s ease-in-out"
2022-06-07 18:29:57 +00:00
: style = "
controls && ! seeking
? 'opacity: 1;'
: 'opacity: 0; pointer-events: none'
"
2022-05-28 01:36:26 +00:00
>
2022-06-08 19:24:47 +00:00
<!-- top controls row -- >
< div
2022-06-08 20:15:15 +00:00
style = "position: absolute; width: 100%; top: 0.25rem"
2022-06-09 05:36:01 +00:00
class = "d-flex justify-center px-2"
2022-06-08 19:24:47 +00:00
>
2022-06-08 20:15:15 +00:00
< minimize / >
2022-06-09 05:36:01 +00:00
< div v-if = "isFullscreen" class="pt-2" @click.self="controlsHandler()" >
2022-06-08 20:15:15 +00:00
< h4 > { { video . title } } < / h4 >
< div style = "color: #aaa; font-size: 0.75rem" >
{ { video . channelName } }
< / div >
2022-06-08 19:24:47 +00:00
< / div >
2022-06-08 20:15:15 +00:00
< v-spacer / >
2022-06-09 05:36:01 +00:00
< captions / >
< loop
v - if = "$refs.player"
class = "mx-2"
: loop = "$refs.player.loop"
2022-07-28 20:20:18 +00:00
@ loop = "
( $refs . player . loop = ! $refs . player . loop ) ,
2022-07-29 05:41:01 +00:00
( $refs . audio . loop = ! $refs . audio . loop ) ,
$store . commit ( 'player/setLoop' , $event )
2022-07-28 20:20:18 +00:00
"
2022-06-09 05:36:01 +00:00
/ >
2022-06-08 20:15:15 +00:00
< close / >
2022-06-08 19:24:47 +00:00
< / div >
<!-- top controls row end -- >
2022-05-01 16:42:26 +00:00
2022-06-08 19:24:47 +00:00
<!-- center controls row -- >
< div
class = "d-flex justify-center align-center"
style = "
transform : translate ( - 50 % , - 50 % ) ;
position : absolute ;
left : 50 % ;
top : 50 % ;
"
>
2022-07-20 03:20:39 +00:00
< v-btn
v - if = "!verticalFullscreen"
fab
text
color = "white"
class = "mx-12"
disabled
>
2022-06-12 04:34:33 +00:00
< v-icon size = "2rem" color = "white" > mdi - skip - previous < / v-icon >
2022-06-08 18:05:00 +00:00
< / v-btn >
< playpause
v - if = "$refs.player"
: video = "$refs.player"
2022-07-31 17:40:24 +00:00
: buffering = "bufferingDetected"
2022-06-24 04:26:44 +00:00
@ play = "$refs.player.play(), $refs.audio.play()"
2022-07-31 17:56:50 +00:00
@ pause = "
$refs . player . pause ( ) ,
$refs . audio . pause ( ) ,
clearTimeout ( bufferingDetected ) ,
( bufferingDetected = false )
"
2022-06-08 18:05:00 +00:00
/ >
2022-06-24 04:26:44 +00:00
< v-btn
2022-07-20 03:20:39 +00:00
v - if = "!verticalFullscreen"
2022-06-24 04:26:44 +00:00
fab
text
color = "white"
class = "mx-12"
@ click = "
$router . push (
` /watch?v= ${ recommends . contents [ 0 ] . videoWithContextRenderer . videoId } `
)
"
>
2022-06-12 04:34:33 +00:00
< v-icon size = "2rem" color = "white" > mdi - skip - next < / v-icon >
2022-06-08 18:05:00 +00:00
< / v-btn >
< / div >
2022-06-08 19:24:47 +00:00
<!-- center controls row end -- >
2022-05-28 05:16:27 +00:00
2022-06-08 20:15:15 +00:00
<!-- time & fullscreen row -- >
< div
2022-06-09 05:36:01 +00:00
: style = "isFullscreen ? 'bottom: 4.25rem' : 'bottom: 0.5rem'"
2022-06-08 20:15:15 +00:00
class = "d-flex justify-between align-center pl-4 pr-2"
style = "position: absolute; width: 100%"
2022-06-09 05:36:01 +00:00
@ click . self = "controlsHandler()"
2022-06-08 20:15:15 +00:00
>
< watchtime
v - if = "$refs.player"
: current - time = "$refs.player.currentTime"
: duration = "$refs.player.duration"
/ >
< v-spacer / >
< fullscreen
style = "z-index: 2"
: fullscreen = "isFullscreen"
2022-06-10 02:34:13 +00:00
@ fullscreen = "fullscreenHandler(true)"
2022-06-08 20:15:15 +00:00
/ >
< / div >
<!-- time & fullscreen row end -- >
2022-06-08 19:24:47 +00:00
<!-- bottom controls row -- >
< div
2022-06-08 20:15:15 +00:00
style = "position: absolute; width: 100%; bottom: 0.5rem"
2022-07-20 00:13:19 +00:00
class = "d-flex justify-between align-center px-2"
2022-06-09 05:36:01 +00:00
@ click . self = "controlsHandler()"
2022-06-07 18:29:57 +00:00
>
2022-07-20 00:11:40 +00:00
< fscontrols
: is - fullscreen = "isFullscreen"
: vertical - fullscreen = "verticalFullscreen"
/ >
2022-06-08 19:24:47 +00:00
< v-spacer / >
<!-- // TODO: merge the bottom 2 into 1 reusable component -->
< quality
2022-07-29 04:44:26 +00:00
v - if = "$refs.player && $refs.player.currentSrc"
2022-06-08 19:24:47 +00:00
: sources = "sources"
: current - source = "$refs.player"
@ quality = "qualityHandler($event)"
/ >
< speed
v - if = "$refs.player"
2022-06-08 20:15:15 +00:00
class = "mx-2"
2022-06-08 19:24:47 +00:00
: current - speed = "$refs.player.playbackRate"
2022-06-24 04:26:44 +00:00
@ speed = "
( $refs . player . playbackRate = $event ) ,
2022-07-28 20:20:18 +00:00
( $refs . audio . playbackRate = $event ) ,
2022-07-28 20:35:38 +00:00
$store . state . player . speedAutosave
? $store . commit ( 'player/setSpeed' , $event )
: { }
2022-06-24 04:26:44 +00:00
"
2022-06-08 19:24:47 +00:00
/ >
< v-btn v-if = "isFullscreen" fab text small disabled @click.stop="" >
< v-icon > mdi - cards - outline < / v-icon >
< / v-btn >
2022-06-08 20:15:15 +00:00
<!-- placeholder for moving fullscreen button above -- >
2022-06-08 19:24:47 +00:00
< v-btn v -else fab text small disabled > < / v-btn >
< / div >
<!-- bottom controls row -- >
2022-05-28 01:36:26 +00:00
< / div >
2022-06-08 19:24:47 +00:00
<!-- controls container end -- >
2022-06-01 18:06:34 +00:00
< progressbar
v - if = "$refs.player"
: current - time = "$refs.player.currentTime"
2022-06-08 16:34:52 +00:00
: duration = "$refs.player.duration"
: fullscreen = "isFullscreen"
: controls = "controls"
2022-06-08 15:59:43 +00:00
: buffered = "buffered"
2022-06-08 16:34:52 +00:00
: seeking = "seeking"
2022-06-01 18:06:34 +00:00
/ >
2022-06-08 19:24:47 +00:00
2022-06-08 20:15:15 +00:00
< sponsorblock
v - if = "$refs.player && blocks.length > 0"
: duration = "$refs.player.duration"
: fullscreen = "isFullscreen"
: controls = "controls"
: seeking = "seeking"
: blocks = "blocks"
/ >
2022-05-28 22:04:35 +00:00
< seekbar
2022-05-28 22:28:41 +00:00
v - if = "$refs.player"
v - show = "!isFullscreen || controls"
2022-06-08 16:42:03 +00:00
: duration = "$refs.player.duration"
2022-05-28 22:04:35 +00:00
: fullscreen = "isFullscreen"
2022-06-08 16:42:03 +00:00
: current - time = "progress"
2022-05-28 22:04:35 +00:00
: video = "$refs.player"
2022-05-29 17:08:21 +00:00
: controls = "controls"
2022-06-08 16:42:03 +00:00
: sources = "sources"
: seeking = "seeking"
2022-05-29 17:08:21 +00:00
@ seeking = "seeking = !seeking"
2022-06-24 04:26:44 +00:00
@ scrub = "
( $refs . player . currentTime = $event ) , ( $refs . audio . currentTime = $event )
"
2022-05-28 22:04:35 +00:00
/ >
2022-07-29 04:44:26 +00:00
< v-progress-circular
v - if = "$store.state.player.preload && buffered < 100"
style = "
transform : translate ( - 50 % , - 50 % ) ;
position : absolute ;
left : 50 % ;
top : 50 % ;
"
: value = "buffered"
color = "primary"
: rotate = "-90"
: size = "64"
>
< b > { { buffered } } % < / b >
< / v-progress-circular >
2022-03-30 12:32:08 +00:00
< / div >
< / template >
< script >
2022-05-28 05:16:27 +00:00
import loop from "~/components/Player/loop.vue" ;
2022-05-28 22:28:41 +00:00
import close from "~/components/Player/close.vue" ;
2022-05-28 05:16:27 +00:00
import speed from "~/components/Player/speed.vue" ;
2022-05-21 02:01:39 +00:00
import seekbar from "~/components/Player/seekbar.vue" ;
2022-05-28 05:16:27 +00:00
import quality from "~/components/Player/quality.vue" ;
2022-05-28 22:15:25 +00:00
import minimize from "~/components/Player/minimize.vue" ;
2022-05-28 05:16:27 +00:00
import captions from "~/components/Player/captions.vue" ;
import playpause from "~/components/Player/playpause.vue" ;
import watchtime from "~/components/Player/watchtime.vue" ;
2022-07-20 00:11:40 +00:00
import fscontrols from "~/components/Player/fscontrols.vue" ;
2022-05-28 05:16:27 +00:00
import fullscreen from "~/components/Player/fullscreen.vue" ;
2022-06-01 18:06:34 +00:00
import progressbar from "~/components/Player/progressbar.vue" ;
2022-06-01 03:40:36 +00:00
import sponsorblock from "~/components/Player/sponsorblock.vue" ;
2022-03-30 12:32:08 +00:00
export default {
2022-04-29 11:49:32 +00:00
components : {
2022-06-01 03:40:36 +00:00
sponsorblock ,
2022-06-01 18:06:34 +00:00
progressbar ,
2022-05-28 05:16:27 +00:00
fullscreen ,
2022-07-20 00:11:40 +00:00
fscontrols ,
2022-05-28 05:16:27 +00:00
watchtime ,
playpause ,
captions ,
2022-05-28 22:15:25 +00:00
minimize ,
2022-05-28 05:16:27 +00:00
quality ,
2022-05-01 16:42:26 +00:00
seekbar ,
2022-05-28 05:16:27 +00:00
speed ,
2022-05-28 22:28:41 +00:00
close ,
2022-05-28 05:16:27 +00:00
loop ,
} ,
props : {
2022-06-21 23:20:05 +00:00
video : {
2022-06-18 00:58:36 +00:00
type : Object ,
required : true ,
} ,
2022-06-21 23:20:05 +00:00
sources : {
type : Array ,
2022-05-29 17:08:21 +00:00
required : true ,
} ,
2022-06-21 23:20:05 +00:00
recommends : {
type : Array ,
} ,
2022-04-29 11:49:32 +00:00
} ,
2022-03-30 12:32:08 +00:00
data ( ) {
return {
2022-05-28 01:36:26 +00:00
isFullscreen : false ,
2022-06-10 02:34:13 +00:00
fullscreenLock : false ,
2022-07-20 03:20:39 +00:00
shortTransition : false ,
2022-06-10 02:34:13 +00:00
verticalFullscreen : false ,
midRotation : false ,
2022-05-28 01:36:26 +00:00
controls : false ,
2022-05-29 17:08:21 +00:00
seeking : false ,
2022-05-28 22:28:41 +00:00
contain : true ,
2022-06-09 01:48:33 +00:00
skipping : 0 ,
2022-06-08 15:59:43 +00:00
progress : 0 ,
buffered : 0 ,
watched : 0 ,
blocks : [ ] ,
2022-04-29 01:44:37 +00:00
vidSrc : "" ,
2022-06-24 04:26:44 +00:00
audSrc : "" ,
2022-08-01 02:56:28 +00:00
isVerticalVideo : false , // maybe rename(refactor everywhere used) to isShort
2022-07-31 17:40:24 +00:00
bufferingDetected : false ,
2022-08-01 02:56:28 +00:00
isMusic : false ,
2022-03-30 12:32:08 +00:00
} ;
} ,
mounted ( ) {
2022-05-28 01:36:26 +00:00
console . log ( "sources" , this . sources ) ;
2022-06-21 23:20:05 +00:00
console . log ( "recommends" , this . recommends ) ;
2022-06-08 15:59:43 +00:00
let vid = this . $refs . player ;
2022-07-27 22:32:12 +00:00
// TODO: this.$store.state.player.quality, check if exists and select the closest one
2022-08-01 02:56:28 +00:00
if ( this . $store . state . player . preload ) this . prebuffer ( this . sources [ 5 ] . url ) ;
2022-07-27 22:32:12 +00:00
else {
this . audSrc = this . sources [ this . sources . length - 1 ] . url ;
2022-08-01 02:56:28 +00:00
this . vidSrc = this . sources [ 5 ] . url ;
2022-07-27 22:32:12 +00:00
}
2022-06-10 03:29:40 +00:00
this . $youtube . getSponsorBlock ( this . video . id , ( data ) => {
2022-08-01 02:56:28 +00:00
// console.warn("sbreturn", data);
2022-06-08 15:59:43 +00:00
if ( Array . isArray ( data ) ) {
this . blocks = data ;
2022-08-01 02:56:28 +00:00
data . find ( ( block ) => {
if ( block . category === "music_offtopic" ) {
this . isMusic = true ;
this . $refs . audio . playbackRate = 1 ;
this . $refs . player . playbackRate = 1 ;
}
} ) ;
2022-06-08 15:59:43 +00:00
}
} ) ;
2022-08-01 02:56:28 +00:00
// TODO: detect this.isMusic from the video or channel metadata instead of just SB segments
2022-08-01 03:02:04 +00:00
this . $refs . player . addEventListener ( "loadeddata" , ( e ) => {
2022-06-08 15:59:43 +00:00
// console.log(e);
2022-07-31 17:40:24 +00:00
// if (vid.networkState === vid.NETWORK_LOADING) {
// // The user agent is actively trying to download data.
// }
// if (vid.readyState < vid.HAVE_FUTURE_DATA) {
// // There is not enough data to keep playing from this point
// }
2022-06-08 15:59:43 +00:00
if ( vid . readyState >= 3 ) {
2022-06-24 04:26:44 +00:00
this . $refs . audio . play ( ) ;
2022-07-31 17:40:24 +00:00
this . bufferingDetected = false ;
2022-07-27 22:32:12 +00:00
this . $refs . audio . currentTime = vid . currentTime ;
2022-08-01 02:56:28 +00:00
if ( ! this . isMusic ) {
this . $refs . audio . playbackRate = this . $store . state . player . speed ;
this . $refs . player . playbackRate = this . $store . state . player . speed ;
} else {
this . $refs . audio . playbackRate = 1 ;
this . $refs . player . playbackRate = 1 ;
}
2022-07-29 05:41:01 +00:00
this . $refs . player . loop = this . $store . state . player . loop ;
this . $refs . audio . loop = this . $store . state . player . loop ;
2022-08-01 03:02:04 +00:00
this . $refs . player . addEventListener ( "timeupdate" , ( ) => {
2022-06-08 16:42:03 +00:00
if ( ! this . seeking ) this . progress = vid . currentTime ; // for seekbar
2022-06-08 15:59:43 +00:00
2022-06-08 16:32:04 +00:00
// console.log("sb check", this.blocks);
2022-06-08 15:59:43 +00:00
// iterate over data.segments array
2022-06-08 16:42:03 +00:00
// for sponsorblock
2022-06-08 15:59:43 +00:00
if ( this . blocks . length > 0 )
this . blocks . forEach ( ( sponsor ) => {
let vidTime = vid . currentTime ;
if (
vidTime >= sponsor . segment [ 0 ] &&
vidTime <= sponsor . segment [ 1 ]
) {
console . log ( "Skipping the sponsor" ) ;
this . $youtube . showToast ( "Skipped sponsor" ) ;
2022-08-01 03:49:24 +00:00
this . $refs . player . currentTime = sponsor . segment [ 1 ] + 1 ;
this . $refs . audio . currentTime = this . $refs . player . currentTime ;
2022-06-08 15:59:43 +00:00
}
} ) ;
} ) ;
2022-07-31 17:40:24 +00:00
// TODO: handle video ending with a "replay" button instead of <playpause /> if not on loop
2022-07-27 22:32:12 +00:00
// TODO: split buffering into multiple sections as it should be for back/forth scrubbing
2022-08-01 03:02:04 +00:00
this . $refs . player . addEventListener ( "progress" , ( ) => {
2022-07-31 17:56:50 +00:00
if ( this . bufferingDetected ) {
this . $refs . audio . currentTime = vid . currentTime ;
clearTimeout ( this . bufferingDetected ) ;
this . bufferingDetected = false ;
}
2022-08-01 03:49:24 +00:00
if ( this . $refs . audio . paused && ! this . $refs . player . paused ) this . $refs . audio . play ( ) ;
2022-06-08 15:59:43 +00:00
this . buffered = ( vid . buffered . end ( 0 ) / vid . duration ) * 100 ;
} ) ;
2022-07-31 17:40:24 +00:00
// buffering detection & sync
2022-08-01 02:56:28 +00:00
let threshold = 250 ; //ms after which user perceives buffering
2022-07-31 17:40:24 +00:00
2022-08-01 03:02:04 +00:00
this . $refs . player . addEventListener ( "waiting" , ( ) => {
2022-08-01 03:49:24 +00:00
if ( ! this . $refs . player . paused ) {
2022-07-31 17:56:50 +00:00
this . bufferingDetected = setTimeout ( ( ) => {
this . bufferingDetected = true ;
this . $refs . audio . pause ( ) ;
//show buffering
} , threshold ) ;
}
2022-07-31 17:40:24 +00:00
} ) ;
2022-08-01 03:02:04 +00:00
this . $refs . player . addEventListener ( "playing" , ( ) => {
2022-07-31 17:40:24 +00:00
if ( this . bufferingDetected != false ) {
clearTimeout ( this . bufferingDetected ) ;
this . $refs . audio . currentTime = vid . currentTime ;
this . bufferingDetected = false ;
2022-07-31 17:56:50 +00:00
this . $refs . audio . play ( ) ;
2022-07-31 17:40:24 +00:00
}
} ) ;
2022-06-08 15:59:43 +00:00
}
} ) ;
2022-06-10 02:34:13 +00:00
} ,
created ( ) {
screen . orientation . addEventListener ( "change" , ( ) =>
this . fullscreenHandler ( false )
) ;
2022-03-30 12:32:08 +00:00
} ,
2022-05-28 22:33:43 +00:00
beforeDestroy ( ) {
2022-08-01 02:56:28 +00:00
this . cleanup ( ) ;
2022-05-28 22:33:43 +00:00
} ,
2022-03-30 12:32:08 +00:00
methods : {
2022-08-01 02:56:28 +00:00
cleanup ( ) {
2022-08-01 03:02:04 +00:00
if ( this . xhr ) this . xhr . abort ( ) ;
2022-08-01 02:56:28 +00:00
if ( this . isFullscreen ) this . exitFullscreen ( ) ;
2022-08-01 03:02:04 +00:00
if ( this . bufferingDetected ) clearTimeout ( this . bufferingDetected ) ;
2022-08-01 02:56:28 +00:00
screen . orientation . removeEventListener ( "change" ) ;
2022-08-01 03:49:24 +00:00
//! this.$refs.player.removeEventListener("loadeddata"); // NOTE: needs a function to be passed as the 2nd argument, but breaks if called with vue method as the 2nd argument in mounted()
// this.$refs.player.removeEventListener("timeupdate");
this . $refs . player . removeEventListener ( "progress" , ( ) => { } ) ;
this . $refs . player . removeEventListener ( "waiting" , ( ) => { } ) ;
this . $refs . player . removeEventListener ( "playing" , ( ) => { } ) ;
2022-08-01 02:56:28 +00:00
} ,
2022-07-27 22:32:12 +00:00
prebuffer ( url ) {
2022-07-29 04:44:26 +00:00
this . xhr = new XMLHttpRequest ( ) ;
this . xhr . open ( "GET" , url , true ) ;
this . xhr . responseType = "blob" ;
2022-07-27 22:32:12 +00:00
2022-07-29 04:44:26 +00:00
this . xhr . addEventListener (
2022-07-27 22:32:12 +00:00
"load" ,
2022-07-28 03:14:57 +00:00
( ) => {
2022-07-29 04:44:26 +00:00
if ( this . xhr . status === 200 ) {
var blob = this . xhr . response ;
console . error ( this . xhr ) ;
2022-07-28 03:14:57 +00:00
this . blobToDataURL ( blob , ( dataurl ) => {
console . log ( dataurl ) ;
this . vidSrc = dataurl ;
2022-07-29 04:44:26 +00:00
this . buffered = 100 ;
2022-07-28 03:14:57 +00:00
} ) ;
2022-07-27 22:32:12 +00:00
} else {
2022-07-29 04:44:26 +00:00
console . error ( "errorred pre-fetch" , this . xhr . status ) ;
2022-07-27 22:32:12 +00:00
}
} ,
false
) ;
var prev _pc = 0 ;
2022-07-29 04:44:26 +00:00
this . xhr . addEventListener ( "progress" , ( event ) => {
2022-07-27 22:32:12 +00:00
if ( event . lengthComputable ) {
var pc = Math . round ( ( event . loaded / event . total ) * 100 ) ;
if ( pc != prev _pc ) {
prev _pc = pc ; // ##%
2022-07-29 04:44:26 +00:00
if ( pc < 100 ) this . buffered = pc ;
2022-08-01 02:56:28 +00:00
// console.warn(this.xhr);
2022-07-27 22:32:12 +00:00
}
}
} ) ;
2022-07-29 04:44:26 +00:00
this . xhr . send ( ) ;
2022-07-27 22:32:12 +00:00
} ,
2022-07-31 17:40:24 +00:00
// !NOTE: (BUG) too big to process for 1080p vids over 2 minutes
2022-07-28 03:14:57 +00:00
blobToDataURL ( blob , callback ) {
var a = new FileReader ( ) ;
a . onload = function ( e ) {
callback ( e . target . result ) ;
} ;
a . readAsDataURL ( blob ) ;
} ,
2022-07-20 03:20:39 +00:00
shortNext ( ) {
this . shortTransition = true ;
setTimeout ( ( ) => {
this . $router . push (
` /watch?v= ${ this . recommends . contents [ 0 ] . videoWithContextRenderer . videoId } `
) ;
} , 150 ) ;
} ,
2022-06-09 01:48:33 +00:00
// TODO: make accumulative onclick after first dblclick (don't set timeout untill stopped clicking)
2022-06-09 01:02:16 +00:00
skipHandler ( time ) {
this . skipping = time ;
setTimeout ( ( ) => {
this . skipping = false ;
2022-06-09 01:48:33 +00:00
} , 500 ) ;
2022-06-09 01:02:16 +00:00
this . $refs . player . currentTime += time ;
2022-06-24 04:26:44 +00:00
this . $refs . audio . currentTime += time ;
2022-06-09 01:02:16 +00:00
} ,
controlsHandler ( ) {
if ( ! this . seeking )
this . controls
? ( clearTimeout ( this . controls ) , ( this . controls = false ) )
: setTimeout ( ( ) => {
2022-06-09 02:01:22 +00:00
if ( ! this . skipping ) {
2022-06-09 01:02:16 +00:00
this . controls = setTimeout ( ( ) => {
2022-06-09 01:48:33 +00:00
if ( ! this . seeking && ! this . $refs . player . paused )
this . controls = false ;
2022-06-09 01:02:16 +00:00
} , 2345 ) ;
}
2022-06-09 02:01:22 +00:00
} , 250 ) ;
2022-06-09 01:02:16 +00:00
} ,
2022-06-08 17:56:14 +00:00
qualityHandler ( q ) {
console . log ( q ) ;
let time = this . $refs . player . currentTime ;
2022-06-24 04:26:44 +00:00
let speed = this . $refs . player . playbackRate ;
2022-06-08 17:56:14 +00:00
this . $refs . player . src = q ;
2022-06-24 04:26:44 +00:00
this . $refs . audio . currentTime = time ;
2022-06-08 17:56:14 +00:00
this . $refs . player . currentTime = time ;
2022-06-24 04:26:44 +00:00
this . $refs . player . playbackRate = speed ;
this . $refs . audio . playbackRate = speed ;
2022-06-08 17:56:14 +00:00
} ,
2022-06-10 02:34:13 +00:00
checkDimensions ( ) {
if ( this . $refs . player . videoHeight > this . $refs . player . videoWidth ) {
this . isVerticalVideo = true ;
2022-07-20 03:20:39 +00:00
this . fullscreenHandler ( true ) ;
this . controlsHandler ( ) ;
2022-05-28 01:36:26 +00:00
} else {
2022-06-10 02:34:13 +00:00
this . isVerticalVideo = false ;
2022-03-30 12:32:08 +00:00
}
} ,
2022-06-10 02:34:13 +00:00
fullscreenHandler ( pressedFullscreenBtn ) {
// Prevent fullscreen button press from being handled twice
// (once by pressing fullscreen button, another by the resulting rotation)
if ( this . midRotation ) {
this . midRotation = false ;
return ;
}
// Toggle fullscreen state
if ( this . isFullscreen ) {
this . exitFullscreen ( pressedFullscreenBtn ) ;
} else {
this . enterFullscreen ( pressedFullscreenBtn ) ;
}
} ,
exitFullscreen ( unlock ) {
if ( unlock ) {
if ( this . verticalFullscreen ) {
// Unset vertical fullscreen mode
screen . orientation . unlock ( ) ;
this . fullscreenLock = false ;
this . verticalFullscreen = false ;
} else {
// Unset standard fullscreen mode
this . midRotation = true ;
screen . orientation . lock ( "portrait" ) ;
this . fullscreenLock = true ;
// Locks the rotation to portrait for two seconds,
// and will then rotate back to landscape if the
// user doesn't rotate first
setTimeout ( ( ) => {
this . fullscreenLock = false ;
screen . orientation . unlock ( ) ;
} , 2 * 1000 ) ;
}
}
2022-05-28 22:33:43 +00:00
this . $vuetube . navigationBar . show ( ) ;
this . $vuetube . statusBar . show ( ) ;
this . isFullscreen = false ;
} ,
2022-06-10 02:34:13 +00:00
enterFullscreen ( force ) {
if ( force ) {
this . fullscreenLock = true ;
if ( this . isVerticalVideo ) {
// Vertical fullscreen mode (vertical video only)
screen . orientation . lock ( "portrait" ) ;
this . verticalFullscreen = true ;
} else {
// Standard fullscreen mode
this . midRotation = true ;
screen . orientation . lock ( "landscape" ) ;
}
}
2022-05-28 22:33:43 +00:00
this . $vuetube . navigationBar . hide ( ) ;
this . $vuetube . statusBar . hide ( ) ;
this . isFullscreen = true ;
} ,
2022-04-29 01:44:37 +00:00
getPlayer ( ) {
return this . $refs . player ;
2022-03-30 12:32:08 +00:00
} ,
} ,
} ;
< / script >
2022-05-28 22:33:43 +00:00
< style >
. dim {
2022-06-08 20:15:15 +00:00
filter : brightness ( 33 % ) ;
2022-05-28 22:33:43 +00:00
}
2022-07-20 03:20:39 +00:00
. dim - ish {
filter : brightness ( 66 % ) ;
}
2022-05-29 17:08:21 +00:00
. invisible {
opacity : 0 ;
}
2022-05-28 22:33:43 +00:00
< / style >