extends includes/layout include includes/video-list-item include includes/comment include includes/subscribe-button include includes/toasts include includes/video-player-controls block head unless error title= `${video.title} - EirTube` else title Error - EirTube +toast_js() script(type="module" src=getStaticURL("html", "/static/js/player-new.js")) script(type="module" src=getStaticURL("html", "/static/js/chapter-highlight.js")) //- script const data = !{JSON.stringify({...video, continuous})}; script const data = !{JSON.stringify({sbData: video.sbData, videoId: video.videoId, lengthSeconds: video.lengthSeconds, comments: video.comments, continuous})}; | const videoPath = !{`"${videoPath}${mediaFragment}"`}; const startingFormat = !{JSON.stringify(startingFormat)}; | const targetFormat = !{JSON.stringify(targetFormat)}; let awaitingNewFormat = !{awaitingNewFormat}; const dlStatus = !{dlStatus}; awaitingThumb = !{awaitingThumb}; //- Sponsorblock settings - let sbSettings = {} - for (const k of Object.keys(settings)) - if (k.startsWith("sponsorblock")) - sbSettings[k] = settings[k] script const sbSettings = !{JSON.stringify(sbSettings)} - if (video.sbData && video.sbData.length > 0) script(type="module" src=getStaticURL("html", "/static/js/sb.js")) - if (settings.dearrow > 0 && settings.dearrow_preload == 0) script const dearrow_thumbnail_instance = "!{settings.dearrow_thumbnail_instance}" script(video-class="related-video" src=getStaticURL("html", "/static/js/dearrow-load.js")) mixin noscript-quality-select(format, disabled, preloading) a(disabled=disabled href=`/watch?v=${video.videoId}&quality=${format.qualityLabel}`).border-look.quality-select-noscript= `${format.cloudtube__label}${preloading ? " (preloading)" : ""}` mixin recommended-videos() .related-cols h2.related-header Related videos if video.recommendedVideos.length .continuous-start a(href=`/watch?v=${video.videoId}&continuous=1` nofollow) Continuous mode each r in video.recommendedVideos +video_list_item("related-video", r, { settings: settings }) block content unless error if continuous - const first = video.recommendedVideos[0] if first script(type="module" src=getStaticURL("html", "/static/js/continuous.js")) noscript meta(http-equiv="refresh" content=`${video.lengthSeconds+5};url=/watch?v=${first.videoId}&continuous=1&session-watched=${sessionWatchedNext}`) .video-page(class={ "video-page--recommended-side": settings.recommended_mode === 0, "video-page--recommended-below": settings.recommended_mode === 1, "video-page--recommended-hidden": settings.recommended_mode === 2 }) main.main-video-section .video-container if targetFormat .video-container-inner video(controls playsinline preload="auto" width=targetFormat.second__width height=targetFormat.second__height data-itag=targetFormat.itag autoplay=continuous||autoplay).video source(type=targetFormat.type src=`${videoPath}${mediaFragment}`) //- source(type=targetFormat.type) each t in video.captions track(label=t.label kind="subtitles" srclang=t.languageCode src=t.url) //- fallback: flash player - let flashvars = new URLSearchParams({skin: "/static/flash/skin.swf", video: `${videoPath}${mediaFragment}`}) embed(type="application/x-shockwave-flash" src="/static/flash/player.swf" id="f4Player" width=1280 height=720 flashvars=flashvars.toString() allowscriptaccess="always" allowfullscreen="true" bgcolor="#000000") //- I hate noscript. its so ugly. but this works somehow noscript link(rel="stylesheet" type="text/css" href="/static/css/noscript-video-controls-hider.css") +video-player-controls(video, formats, startingFormat, awaitingThumb) //- SponsorBlock popup #sb-skip-prompt.hidden .row img(src=`/static/images/sponsorblock-logo.png`).sponsorblock-logo-video #reason Skipped sponsor .row #timer 9 seconds #btn= `Unskip (${settings.sponsorblock_keybind} or click)` else video(src="").video .stream-notice The server provided no playback streams. .info header.info-main .video-title-area if settings.dearrow > 0 && video.dearrowData && video.dearrowData.title input(type="checkbox" checked=(settings.dearrow != 1) class={ "dearrow-button-video": true }) hi.title.alt= video.dearrowData.title h1.title= video.title .author a(href=`/channel/${video.authorId}`).author-link= `Uploaded by ${video.author}` .info-secondary - const date = new Date(video.published*1000) - const month = new Intl.DateTimeFormat("en-US", {month: "short"}).format(date.getTime()) div= `Uploaded ${date.getUTCDate()} ${month} ${date.getUTCFullYear()}` div= video.second__viewCountText div= video.second__likeCountText if continuous div#continuous-controls.continuous .continuous__description .continuous__title Continuous mode: next video autoplays noscript .continuous__script-warning Without JavaScript, it will trigger on a timer, not on video completion. .continuous__buttons a(href=`/watch?v=${video.videoId}`)#continuous-stop.border-look Turn off .button-container .button-container-left +subscribe_button(video.authorId, subscribed, `/watch?v=${video.videoId}`).border-look a(href=req.url).border-look Share a(href=`https://www.youtube.com/watch?v=${video.videoId}`).border-look YouTube //- a(href=`https://redirect.invidious.io/watch?v=${video.videoId}`).border-look Invidious .button-container-right .button-container-right-top #quality-select-noscript-parent each f in formats +noscript-quality-select(f, f.itag == startingFormat.itag, awaitingNewFormat && targetFormat.itag == f.itag) .button-container-right-bottom form(method="get" action="/redownloadVideo") input(type="hidden" name="videoID" value=video.videoId) input(type="hidden" id="data-quality" name="quality" value=quality) button.border-look.redownloadBtn Redownload a(href=`${videoPath}&dl=1` id="download-btn").border-look= `Download ${startingFormat.cloudtube__label.replace(" *", "")} (${startingFormat.eirtube__size})` a(href=`/getOgg?videoID=${video.videoId}-${startingFormat.qualityLabel}` id="download-ogg-btn").border-look= `Download audio` noscript if awaitingNewFormat .stream-notice p | Since you are not using JavaScript, your browser will cache the video. br | Press CTRL+F5 if the video errors or skips to the end suddenly. .description#description!= video.descriptionHtml #below-video-container if !continuous && settings.recommended_mode == 1 input(type="radio" name="below" checked=true)#radio-comments input(type="radio" name="below")#radio-recommended .below-video-radio-container label(for="radio-comments").below-video-radio-label Comments label(for="radio-recommended").below-video-radio-label Recommended //- aside#standard-related-videos.related-videos aside#recommended-videos +recommended-videos() aside#comments - const commentCount = (video.comments && video.comments.commentCount) ? video.comments.commentCount : 0 h1= `${commentCount.toLocaleString("en-US")} comment${commentCount != 1 ? "s" : ""}` //- TODO: comment sorting buttons if video.comments && video.comments.comments each comment in video.comments.comments +comment("video-comment", comment, `https://www.youtube.com/watch?v=${video.videoId}&lc={}`, video.videoId) //- TODO: comment continuation button //- Standard view if !continuous && settings.recommended_mode == 0 aside#standard-related-videos.related-videos +recommended-videos() //- Continuous view if continuous aside.related-videos#continuous-related-videos - let column = video.recommendedVideos.filter(v => !sessionWatched.includes(v.videoId)) if column.length .related-cols h2.related-header Autoplay next #continuous-first +video_list_item("related-video", column.shift(), { continuous: true, settings: settings }) if column.length .related-cols h2.related-header Related videos each r in column +video_list_item("related-video", r, { continuous: true, settings: settings }) //- keep on continuous mode for all recommendations #toast-container each toast in toasts +toast(toast.color, toast.icon, toast.text, toast.noFade) noscript +toast(undefined, "loading", `Loading ${startingFormat.qualityLabel}...`) else //- error main.video-error-page h2 Error != message p: a(href=`https://www.youtube.com/watch?v=${video.videoId}`) Watch on YouTube →