您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
This script forces the rounded version of the layout (which includes some fewer tweaks applied, which also improves bugs).
// ==UserScript== // @name YouTube - Force rounded corners + tweaks included // @version 2025.07.11 // @description This script forces the rounded version of the layout (which includes some fewer tweaks applied, which also improves bugs). // @author Joey_JTS (original author: xX_LegendCraftd_Xx) // @license MIT // @match *://www.youtube.com/* // @match *://m.youtube.com/* // @namespace https://gf.qytechs.cn/en/users/933798 // @icon https://www.youtube.com/favicon.ico // @run-at document-idle // @grant none // ==/UserScript== // Attributes to remove from <html> const ATTRS = [ "darker-dark-theme", "darker-dark-theme-deprecate" ]; // Regular config keys. const CONFIGS = { BUTTON_REWORK: true } // Experiment flags. const EXPFLAGS = { /* Force rounded corners */ web_button_rework: true, web_button_rework_with_live: true, web_darker_dark_theme: true, web_filled_subscribed_button: true, web_guide_ui_refresh: true, web_modern_ads: true, web_modern_buttons: true, web_modern_chips: true, web_modern_dialogs: true, web_modern_playlists: true, web_modern_subscribe: true, web_rounded_containers: true, web_rounded_thumbnails: true, web_searchbar_style: "rounded_corner_borders_light_btn", web_segmented_like_dislike_button: true, web_sheets_ui_refresh: true, web_snackbar_ui_refresh: true, /* Force rounded watch layout and few tweaks to be included (such as disabling the useless 'watch grid' UI */ kevlar_watch_metadata_refresh: true, kevlar_watch_metadata_refresh_attached_subscribe: true, kevlar_watch_metadata_refresh_clickable_description: true, kevlar_watch_metadata_refresh_compact_view_count: true, kevlar_watch_metadata_refresh_description_info_dedicated_line: true, kevlar_watch_metadata_refresh_description_inline_expander: true, kevlar_watch_metadata_refresh_description_primary_color: true, kevlar_watch_metadata_refresh_for_live_killswitch: true, kevlar_watch_metadata_refresh_full_width_description: true, kevlar_watch_metadata_refresh_narrower_item_wrap: true, kevlar_watch_metadata_refresh_relative_date: true, kevlar_watch_metadata_refresh_top_aligned_actions: true, kevlar_watch_modern_metapanel: true, kevlar_watch_modern_panels: true, kevlar_watch_panel_height_matches_player: true, kevlar_watch_grid: false, kevlar_watch_grid_hide_chips: false, small_avatars_for_comments: false, small_avatars_for_comments_ep: false, web_watch_compact_comments: false, web_watch_compact_comments_ep: false, web_watch_theater_chat: false, web_watch_theater_fixed_chat: false, live_chat_over_engagement_panels: false, live_chat_scaled_height: false, live_chat_smaller_min_height: false, wn_grid_max_item_width: 0, wn_grid_min_item_width: 0, kevlar_set_internal_player_size: false, kevlar_watch_flexy_metadata_height: "136", kevlar_watch_max_player_width: "1280", web_watch_rounded_player_large: false, desktop_delay_player_resizing: false, /* Additional tweaks (which includes disabling ambient lighting and reverting new UI changes except for both web_modern_tabs and web_enable_youtab configs ) */ kevlar_refresh_on_theme_change: false, smartimation_background: false, web_animated_actions: false, web_animated_like: false, web_animated_like_lazy_load: false, enable_channel_page_header_profile_section: false, kevlar_modern_sd_v2: false, web_modern_collections_v2: false, web_modern_tabs: false, web_modern_typography: true, web_enable_youtab: true, kevlar_measure_ambient_mode_idle: false, kevlar_watch_cinematics_invisible: false, web_cinematic_theater_mode: false, web_cinematic_fullscreen: false, enable_cinematic_blur_desktop_loading: false, kevlar_watch_cinematics: false, web_cinematic_masthead: false, web_watch_cinematics_preferred_reduced_motion_default_disabled: false } // Player flags // !!! USE STRINGS FOR VALUES !!! // For example: "true" instead of true const PLYRFLAGS = { web_rounded_containers: "true", web_rounded_thumbnails: "true" } class YTP { static observer = new MutationObserver(this.onNewScript); static _config = {}; static isObject(item) { return (item && typeof item === "object" && !Array.isArray(item)); } static mergeDeep(target, ...sources) { if (!sources.length) return target; const source = sources.shift(); if (this.isObject(target) && this.isObject(source)) { for (const key in source) { if (this.isObject(source[key])) { if (!target[key]) Object.assign(target, { [key]: {} }); this.mergeDeep(target[key], source[key]); } else { Object.assign(target, { [key]: source[key] }); } } } return this.mergeDeep(target, ...sources); } static onNewScript(mutations) { for (var mut of mutations) { for (var node of mut.addedNodes) { YTP.bruteforce(); } } } static start() { this.observer.observe(document, {childList: true, subtree: true}); } static stop() { this.observer.disconnect(); } static bruteforce() { if (!window.yt) return; if (!window.yt.config_) return; this.mergeDeep(window.yt.config_, this._config); } static setCfg(name, value) { this._config[name] = value; } static setCfgMulti(configs) { this.mergeDeep(this._config, configs); } static setExp(name, value) { if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {}; this._config.EXPERIMENT_FLAGS[name] = value; } static setExpMulti(exps) { if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {}; this.mergeDeep(this._config.EXPERIMENT_FLAGS, exps); } static decodePlyrFlags(flags) { var obj = {}, dflags = flags.split("&"); for (var i = 0; i < dflags.length; i++) { var dflag = dflags[i].split("="); obj[dflag[0]] = dflag[1]; } return obj; } static encodePlyrFlags(flags) { var keys = Object.keys(flags), response = ""; for (var i = 0; i < keys.length; i++) { if (i > 0) { response += "&"; } response += keys[i] + "=" + flags[keys[i]]; } return response; } static setPlyrFlags(flags) { if (!window.yt) return; if (!window.yt.config_) return; if (!window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS) return; var conCfgs = window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS; if (!("WEB_PLAYER_CONTEXT_CONFIGS" in this._config)) this._config.WEB_PLAYER_CONTEXT_CONFIGS = {}; for (var cfg in conCfgs) { var dflags = this.decodePlyrFlags(conCfgs[cfg].serializedExperimentFlags); this.mergeDeep(dflags, flags); this._config.WEB_PLAYER_CONTEXT_CONFIGS[cfg] = { serializedExperimentFlags: this.encodePlyrFlags(dflags) } } } } window.addEventListener("yt-page-data-updated", function tmp() { YTP.stop(); for (i = 0; i < ATTRS.length; i++) { document.getElementsByTagName("html")[0].removeAttribute(ATTRS[i]); } window.removeEventListener("yt-page-date-updated", tmp); }); YTP.start(); YTP.setCfgMulti(CONFIGS); YTP.setExpMulti(EXPFLAGS); YTP.setPlyrFlags(PLYRFLAGS); function $(q) { return document.querySelector(q); } (function() { let css = ` /* Add rounded corners under the player */ div#ytp-id-17.ytp-popup.ytp-settings-menu, div#ytp-id-18.ytp-popup.ytp-settings-menu { border-radius: 12px !important } div.branding-context-container-inner.ytp-rounded-branding-context { border-radius: 8px !important } .iv-card { border-radius: 8px !important } .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-overlay-image img, .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-text-overlay, .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-enhanced-overlay { border-radius: 8px !important } .ytp-tooltip.ytp-text-detail.ytp-preview .ytp-tooltip-bg { border-top-left-radius: 12px !important; border-bottom-left-radius: 12px !important } .ytp-tooltip.ytp-text-detail.ytp-preview { border-radius: 12px !important } .ytp-ce-video.ytp-ce-medium, .ytp-ce-playlist.ytp-ce-medium, .ytp-ce-medium .ytp-ce-expanding-overlay-background { border-radius: 8px !important } .ytp-autonav-endscreen-upnext-thumbnail { border-radius: 8px !important } .ytp-autonav-endscreen-upnext-button { border-radius: 18px !important } .ytp-videowall-still-image { border-radius: 8px !important } .ytp-sb-subscribe, .ytp-sb-unsubscribe { border-radius: 18px !important } /* Watch page tweaks (including the 'Revert video list' CSS) */ ytd-watch-flexy[rounded-player-large]:not([fullscreen]):not([theater]) #ytd-player.ytd-watch-flexy, ytd-watch-flexy[rounded-player] #ytd-player.ytd-watch-flexy { border-radius: 0px !important } #actions.ytd-watch-metadata { min-width: auto !important } ytd-watch-flexy[default-layout][reduced-top-margin] #primary.ytd-watch-flexy, ytd-watch-flexy[default-layout][reduced-top-margin] #secondary.ytd-watch-flexy { padding-top: var(--ytd-margin-6x) !important } ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata, ytd-watch-metadata[title-headline-m] h1.ytd-watch-metadata { font-family: "YouTube Sans","Roboto",sans-serif !important; font-weight: 600 !important; font-size: 2rem !important; line-height: 2.8rem !important } ytd-comments-header-renderer[compact-header] #title.ytd-comments-header-renderer { margin-bottom: 24px !important } ytd-comments-header-renderer[modern-typography][compact-header] .count-text.ytd-comments-header-renderer { font-size: 2rem !important; line-height: 2.8rem !important; font-weight: 700 !important; max-height: 2.8rem !important; display: flex !important; flex-direction: row-reverse !important } [compact-header] .count-text.ytd-comments-header-renderer { display: flex !important; flex-direction: row-reverse !important } [compact-header] .count-text.ytd-comments-header-renderer span { margin-right: 6px !important } ytd-watch-flexy #comment-teaser.ytd-watch-metadata { display: none } ytd-watch-flexy ytd-rich-item-renderer[rendered-from-rich-grid] { --ytd-rich-item-row-usable-width: 100% !important } ytd-watch-flexy ytd-rich-item-renderer[rendered-from-rich-grid][is-in-first-column] { margin-left: 0 } ytd-watch-flexy ytd-rich-item-renderer ytd-menu-renderer .ytd-menu-renderer[style-target=button] { width: 24px !important; height: 24px !important } ytd-watch-flexy #dismissible.ytd-rich-grid-media { flex-direction: row } ytd-watch-flexy #attached-survey.ytd-rich-grid-media, ytd-watch-flexy #avatar-link.ytd-rich-grid-media, ytd-watch-flexy #avatar-container.ytd-rich-grid-media { display: none } ytd-watch-flexy ytd-thumbnail.ytd-rich-grid-media, ytd-watch-flexy ytd-playlist-thumbnail.ytd-rich-grid-media { margin-right: 8px; height: 94px; width: 168px } ytd-watch-flexy ytd-thumbnail[size=large] a.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large]:before, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] a.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin]:before { border-radius: 8px } ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-time-status-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-toggle-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-time-status-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-toggle-button-renderer.ytd-thumbnail { margin: 4px } ytd-watch-flexy ytd-rich-item-renderer, ytd-watch-flexy ytd-rich-grid-row #contents.ytd-rich-grid-row { margin: 0 } ytd-watch-flexy ytd-rich-item-renderer[reduced-bottom-margin] { margin-top: 8px; margin-bottom: 0 } ytd-watch-flexy ytd-rich-grid-renderer[reduced-top-margin] #contents.ytd-rich-grid-renderer { padding-top: 0px } ytd-watch-flexy ytd-rich-grid-media { margin-bottom: 8px } ytd-watch-flexy #details.ytd-rich-grid-media { width: 100%; min-width: 0 } ytd-watch-flexy ytd-video-meta-block[rich-meta] #metadata-line.ytd-video-meta-block, ytd-watch-flexy #channel-name.ytd-video-meta-block { font-family: "Roboto", "Arial", sans-serif; font-size: 1.2rem; line-height: 1.8rem; font-weight: 400 } ytd-watch-flexy #video-title.ytd-rich-grid-media { margin: 0 0 4px 0; display: block; font-family: "Roboto", "Arial", sans-serif; font-size: 1.4rem; line-height: 2rem; font-weight: 500; overflow: hidden; display: block; max-height: 4rem; -webkit-line-clamp: 2; display: box; display: -webkit-box; -webkit-box-orient: vertical; text-overflow: ellipsis; white-space: normal } ytd-watch-flexy h3.ytd-rich-grid-media { margin: 0 } ytd-watch-flexy .title-badge.ytd-rich-grid-media, ytd-watch-flexy .video-badge.ytd-rich-grid-media { margin-top: 0 } ytd-watch-flexy ytd-rich-section-renderer.style-scope.ytd-rich-grid-renderer { display: none } ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar] ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer, ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar-on-watch] ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer, ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar-on-home] #header.ytd-rich-grid-renderer ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer { display: flex; height: 51px; margin-bottom: 8px } ytd-watch-flexy #chips-wrapper.ytd-feed-filter-chip-bar-renderer { position: relative; top: 0 } ytd-watch-flexy ytd-feed-filter-chip-bar-renderer[fluid-width] #chips-content.ytd-feed-filter-chip-bar-renderer { padding: 0 } ytd-watch-flexy yt-chip-cloud-chip-renderer.ytd-feed-filter-chip-bar-renderer, ytd-watch-flexy yt-chip-cloud-chip-renderer.ytd-feed-filter-chip-bar-renderer:first-of-type { margin: 8px; margin-left: 0 } ytd-watch-flexy ytd-button-renderer.ytd-feed-filter-chip-bar-renderer { margin: 0; padding: 0 8px } /* More tweaks to be applied (including removal of annoyances) */ #buttons.ytd-c4-tabbed-header-renderer { flex-direction: row-reverse !important } ytd-channel-tagline-renderer { display: block !important; padding: 0 !important } #content.ytd-channel-tagline-renderer::before { content: "More about this channel"; font-weight: 500 !important } #content.ytd-channel-tagline-renderer { max-width: 162px !important } [page-subtype="channels"] .page-header-view-model-wiz__page-header-description { margin-top: 0px !important; max-width: 236px !important } [page-subtype="channels"] yt-description-preview-view-model .truncated-text-wiz__truncated-text-content:before { content: "More about this channel > "; font-weight: 500 !important } ytd-browse[page-subtype="channels"] button.truncated-text-wiz__absolute-button { display: none !important } #avatar.ytd-c4-tabbed-header-renderer, .yt-spec-avatar-shape__button--button-giant { width: 80px !important; height: 80px !important; margin: 0 24px 0 0 !important; flex: none !important; overflow: hidden !important } .yt-spec-avatar-shape__button--button-giant, .yt-spec-avatar-shape--avatar-size-giant, .yt-spec-avatar-shape__button--button-extra-extra-large, .yt-spec-avatar-shape--avatar-size-extra-extra-large { width: 80px !important; height: 80px !important; margin-right: 0px !important; } #avatar-editor.ytd-c4-tabbed-header-renderer { --ytd-channel-avatar-editor-size: 80px !important } #channel-name.ytd-c4-tabbed-header-renderer { margin-bottom: 0 !important } #channel-header-container.ytd-c4-tabbed-header-renderer { padding-top: 0 !important; align-items: center !important } #inner-header-container.ytd-c4-tabbed-header-renderer { margin-top: 0 !important; align-items: center !important } .yt-content-metadata-view-model-wiz--inline .yt-content-metadata-view-model-wiz__metadata-row { margin-top: 0 !important } yt-formatted-string#channel-pronouns.style-scope.ytd-c4-tabbed-header-renderer, #videos-count { display: none !important } .meta-item.ytd-c4-tabbed-header-renderer { display: block !important } div#channel-header-links.style-scope.ytd-c4-tabbed-header-renderer, .page-header-view-model-wiz__page-header-attribution { display: none !important } ytd-c4-tabbed-header-renderer[use-page-header-style] #channel-name.ytd-c4-tabbed-header-renderer, [page-subtype="channels"] .page-header-view-model-wiz__page-header-title--page-header-title-large { font-size: 2.4em !important; font-weight: 400 !important; line-height: var(--yt-channel-title-line-height, 3rem) !important; margin: 0 !important } span.delimiter.style-scope.ytd-c4-tabbed-header-renderer, .yt-content-metadata-view-model-wiz__delimiter { display: none !important } div#meta.style-scope.ytd-c4-tabbed-header-renderer { width: auto !important } ytd-c4-tabbed-header-renderer[use-page-header-style] #inner-header-container.ytd-c4-tabbed-header-renderer { flex-direction: row !important } div.page-header-banner.style-scope.ytd-c4-tabbed-header-renderer { margin-left: 0px !important; margin-right: 8px !important; border-radius: 0px !important } [has-inset-banner] #page-header-banner.ytd-tabbed-page-header { padding-left: 0 !important; padding-right: 0 !important } ytd-c4-tabbed-header-renderer[use-page-header-style] .page-header-banner.ytd-c4-tabbed-header-renderer, .yt-image-banner-view-model-wiz--inset { border-radius: 0px !important } .yt-content-metadata-view-model-wiz__metadata-text { margin-right: 8px !important } [page-subtype="channels"] .yt-content-metadata-view-model-wiz__metadata-text, [page-subtype="channels"] .truncated-text-wiz, [page-subtype="channels"] .truncated-text-wiz__absolute-button { font-size: 1.4rem !important } .yt-tab-shape-wiz { padding: 0 32px !important; margin-right: 0 !important } .yt-tab-shape-wiz__tab { font-size: 14px !important; font-weight: 500 !important; letter-spacing: var(--ytd-tab-system-letter-spacing) !important; text-transform: uppercase !important } .yt-tab-group-shape-wiz__slider { display: none !important } ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-row--metadata-row-inline { display: flex } ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-text:last-of-type { display: none } ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-text:first-of-type { display: flex } ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz--inline { flex-direction: row-reverse } ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-flexible-actions { margin-top: -56px } ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz__action-row { margin-top: 60px } ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz__action { padding-right: 8px } ytd-browse[page-subtype="channels"] span.yt-core-attributed-string--link-inherit-color { font-weight: 400 !important } ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-headline-info { margin-bottom: 8px } #title.ytd-playlist-sidebar-primary-info-renderer, ytd-inline-form-renderer[component-style=INLINE_FORM_STYLE_TITLE] #text-displayed.ytd-inline-form-renderer { font-family: YouTube Sans !important; font-weight: 700 !important } div#end.style-scope.ytd-masthead .yt-spec-icon-badge-shape--style-overlay.yt-spec-icon-badge-shape--type-cart-refresh .yt-spec-icon-badge-shape__badge { color: #fff !important } ytd-button-renderer.ytd-feed-filter-chip-bar-renderer { background-color: transparent !important } #left-arrow-button.ytd-feed-filter-chip-bar-renderer, #right-arrow-button.ytd-feed-filter-chip-bar-renderer { background-color: var(--yt-spec-base-background) !important } #left-arrow.ytd-feed-filter-chip-bar-renderer:after { background: linear-gradient(to right, var(--yt-spec-base-background) 20%, rgba(255, 255, 255, 0) 80%) !important } #right-arrow.ytd-feed-filter-chip-bar-renderer:before { background: linear-gradient(to left, var(--yt-spec-base-background) 20%, rgba(255, 255, 255, 0) 80%) !important } #background.ytd-masthead, #frosted-glass.ytd-app { background: var(--yt-spec-base-background) !important; backdrop-filter: none !important } .ytp-progress-bar .ytp-scrubber-button { opacity: 0 !important } .ytp-progress-bar:hover .ytp-scrubber-button { opacity: 1 !important } [d*="M18 4v15.06l-5.42-3.87-.58-.42-.58.42L6 19.06V4h12m1-1H5v18l7-5 7 5V3z"] { d: path("M22 13h-4v4h-2v-4h-4v-2h4V7h2v4h4v2zm-8-6H2v1h12V7zM2 12h8v-1H2v1zm0 4h8v-1H2v1z") } ytd-action-companion-ad-renderer, ytd-display-ad-renderer, ytd-video-masthead-ad-advertiser-info-renderer, ytd-video-masthead-ad-primary-video-renderer, ytd-in-feed-ad-layout-renderer, ytd-ad-slot-renderer, yt-about-this-ad-renderer, yt-mealbar-promo-renderer, ytd-ad-slot-renderer, ytd-in-feed-ad-layout-renderer, .ytd-video-masthead-ad-v3-renderer, div#root.style-scope.ytd-display-ad-renderer.yt-simple-endpoint, div#sparkles-container.style-scope.ytd-promoted-sparkles-web-renderer, div#main-container.style-scope.ytd-promoted-video-renderer, #player-ads, .ytwPanelAdHeaderImageLockupViewModelHost, ytd-ads-engagement-panel-content-renderer, #content.ytd-ads-engagement-panel-content-renderer, ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"], ad-slot-renderer, ytm-promoted-sparkles-web-renderer, masthead-ad, #masthead-ad, ytd-video-quality-promo-renderer, #yt-lang-alert-container, .YtmPaidContentOverlayHost, .ytd-primetime-promo-renderer, ytd-brand-video-singleton-renderer, #yt-feedback, #yt-hitchhiker-feedback, ytd-merch-shelf-renderer, ytd-enforcement-message-view-model, div[is-shared-heimdall], tp-yt-iron-overlay-backdrop.opened { display: none !important; } #movie_player.ad-showing video { filter: blur(100px) opacity(0.25) grayscale(0.5); } #movie_player.ad-showing .ytp-title, #movie_player.ad-showing .ytp-title-channel, .ytp-visit-advertiser-link, .ytp-ad-visit-advertiser-button, ytmusic-app:has(#movie_player.ad-showing) ytmusic-player-bar :is(.title, .subtitle) { filter: blur(4px) opacity(0.5) grayscale(0.5); transition: 0.05s filter linear; } :is(#movie_player.ad-showing .ytp-title,#movie_player.ad-showing .ytp-title-channel,.ytp-visit-advertiser-link,.ytp-ad-visit-advertiser-button,ytmusic-app:has(#movie_player.ad-showing) ytmusic-player-bar :is(.title,.subtitle)):is(:hover,:focus-within) { filter: none; } .ytp-suggested-action-badge { visibility: hidden !important; } ytd-watch-metadata.ytd-watch-flexy { padding-bottom: 36px !important; } ytd-search-header-renderer .yt-spec-button-shape-next--size-m { flex-direction: row-reverse; } ytd-search-header-renderer .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-trailing .yt-spec-button-shape-next__icon { margin-left: -6px; margin-right: 6px; } /* For YT Mobile */ html[dark] { --yt-spec-base-background: #0f0f0f !important } html:not([dark]) { --yt-spec-base-background: #fff !important } ytm-mobile-topbar-renderer.frosted-glass, ytm-pivot-bar-renderer.frosted-glass, ytm-feed-filter-chip-bar-renderer.frosted-glass { background: var(--yt-spec-base-background) !important; -webkit-backdrop-filter: none !important; backdrop-filter: none !important }`; if (typeof GM_addStyle !== "undefined") { GM_addStyle(css); } else { let styleNode = document.createElement("style"); styleNode.appendChild(document.createTextNode(css)); (document.querySelector("head") || document.documentElement).appendChild(styleNode); } })(); // Integrate 'YouTube Video Resize Fix' script (special thanks to CY Fung) /* jshint esversion:8 */ ((__CONTEXT01__) => { 'use strict'; const win = this instanceof Window ? this : window; // Create a unique key for the script and check if it is already running const hkey_script = 'ahceihvpbosz'; if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting win[hkey_script] = true; const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0); const indr = o => insp(o).$ || o.$ || 0; /** @type {globalThis.PromiseConstructor} */ const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve. const cleanContext = async (win) => { const waitFn = requestAnimationFrame; // shall have been binded to window try { let mx = 16; // MAX TRIAL const frameId = 'vanillajs-iframe-v1' let frame = document.getElementById(frameId); let removeIframeFn = null; if (!frame) { frame = document.createElement('iframe'); frame.id = frameId; const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting) n.appendChild(frame); while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine const root = document.documentElement; root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL)); removeIframeFn = (setTimeout) => { const removeIframeOnDocumentReady = (e) => { e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false); e = n; n = win = removeIframeFn = 0; setTimeout ? setTimeout(() => e.remove(), 200) : e.remove(); } if (!setTimeout || document.readyState !== 'loading') { removeIframeOnDocumentReady(); } else { win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false); } } } while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn); const fc = frame.contentWindow; if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL try { const { requestAnimationFrame, setTimeout, clearTimeout } = fc; const res = { requestAnimationFrame, setTimeout, clearTimeout }; for (let k in res) res[k] = res[k].bind(win); // necessary if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn); return res; } catch (e) { if (removeIframeFn) removeIframeFn(); return null; } } catch (e) { console.warn(e); return null; } }; const isWatchPageURL = (url) => { url = url || location; return location.pathname === '/watch' || location.pathname.startsWith('/live/') }; cleanContext(win).then(__CONTEXT02__ => { if (!__CONTEXT02__) return null; const { ResizeObserver } = __CONTEXT01__; const { requestAnimationFrame, setTimeout, clearTimeout } = __CONTEXT02__; const elements = {}; let rid1 = 0; let rid2 = 0; /** @type {MutationObserver | null} */ let attrObserver = null; /** @type {ResizeObserver | null} */ let resizeObserver = null; let isHTMLAttrApplied = false; const core = { begin() { document.addEventListener('yt-player-updated', core.hanlder, true); document.addEventListener('ytd-navigate-finish', core.hanlder, true); }, hanlder: () => { rid1++; if (rid1 > 1e9) rid1 = 9; const tid = rid1; requestAnimationFrame(() => { if (tid !== rid1) return; core.runner(); }) }, async runner() { if (!location.href.startsWith('https://www.youtube.com/')) return; if (!isWatchPageURL()) return; elements.ytdFlexy = document.querySelector('ytd-watch-flexy'); elements.video = document.querySelector('ytd-watch-flexy #movie_player video, ytd-watch-flexy #movie_player audio.video-stream.html5-main-video'); if (elements.ytdFlexy && elements.video) { } else return; elements.moviePlayer = elements.video.closest('#movie_player'); if (!elements.moviePlayer) return; // resize Video let { ytdFlexy } = elements; if (!ytdFlexy.ElYTL) { ytdFlexy.ElYTL = 1; const ytdFlexyCnt = insp(ytdFlexy); if (typeof ytdFlexyCnt.calculateNormalPlayerSize_ === 'function') { ytdFlexyCnt.calculateNormalPlayerSize_ = core.resizeFunc(ytdFlexyCnt.calculateNormalPlayerSize_, 1); } else { console.warn('ytdFlexyCnt.calculateNormalPlayerSize_ is not a function.') } if (typeof ytdFlexyCnt.calculateCurrentPlayerSize_ === 'function') { ytdFlexyCnt.calculateCurrentPlayerSize_ = core.resizeFunc(ytdFlexyCnt.calculateCurrentPlayerSize_, 0); } else { console.warn('ytdFlexyCnt.calculateCurrentPlayerSize_ is not a function.') } } ytdFlexy = null; // when video is fetched elements.video.removeEventListener('canplay', core.triggerResizeDelayed, false); elements.video.addEventListener('canplay', core.triggerResizeDelayed, false); // when video is resized if (resizeObserver) { resizeObserver.disconnect(); resizeObserver = null; } if (typeof ResizeObserver === 'function') { resizeObserver = new ResizeObserver(core.triggerResizeDelayed); resizeObserver.observe(elements.moviePlayer); } // MutationObserver:[collapsed] @ ytd-live-chat-frame#chat if (attrObserver) { attrObserver.takeRecords(); attrObserver.disconnect(); attrObserver = null; } let chat = document.querySelector('ytd-watch-flexy ytd-live-chat-frame#chat'); if (chat) { // resize due to DOM update attrObserver = new MutationObserver(core.triggerResizeDelayed); attrObserver.observe(chat, { attributes: true, attributeFilter: ["collapsed"] }); chat = null; } // resize on idle Promise.resolve().then(core.triggerResizeDelayed); }, resizeFunc(originalFunc, kb) { return function () { rid2++; if (!isHTMLAttrApplied) { isHTMLAttrApplied = true; Promise.resolve(0).then(() => { document.documentElement.classList.add('youtube-video-resize-fix'); }).catch(console.warn); } if (document.fullscreenElement === null) { // calculateCurrentPlayerSize_ shall be always return NaN to make correct positioning of toolbars if (!kb) return { width: NaN, height: NaN }; let ret = core.calculateSize(); if (ret.height > 0 && ret.width > 0) { return ret; } } return originalFunc.apply(this, arguments); } }, calculateSize_() { const { moviePlayer, video } = elements; const rect1 = { width: video.videoWidth, height: video.videoHeight }; // native values independent of css rules if (rect1.width > 0 && rect1.height > 0) { const rect2 = moviePlayer.getBoundingClientRect(); const aspectRatio = rect1.width / rect1.height; let h2 = rect2.width / aspectRatio; let w2 = rect2.height * aspectRatio; return { rect2, h2, w2 }; } return null; }, calculateSize() { let rs = core.calculateSize_(); if (!rs) return { width: NaN, height: NaN }; const { rect2, h2, w2 } = rs; if (h2 > rect2.height) { return { width: w2, height: rect2.height }; } else { return { width: rect2.width, height: h2 }; } }, triggerResizeDelayed: () => { rid2++; if (rid2 > 1e9) rid2 = 9; const tid = rid2; requestAnimationFrame(() => { if (tid !== rid2) return; const { ytdFlexy } = elements; let r = false; const ytdFlexyCnt = insp(ytdFlexy); const windowSize_ = ytdFlexyCnt.windowSize_; if (windowSize_ && typeof ytdFlexyCnt.onWindowResized_ === 'function') { try { ytdFlexyCnt.onWindowResized_(windowSize_); r = true; } catch (e) { } } if (!r) window.dispatchEvent(new Event('resize')); }) } }; core.begin(); // YouTube Watch Page Reflect (WPR) // This script enhances the functionality of YouTube pages by reflecting changes in the page state. (async function youTubeWPR() { let checkPageVisibilityChanged = false; // A WeakSet to keep track of elements being monitored for mutations. const monitorWeakSet = new WeakSet(); /** @type {globalThis.PromiseConstructor} */ const Promise = (async () => { })().constructor; // Function to reflect the current state of the YouTube page. async function _reflect() { await Promise.resolve(); const youtubeWpr = document.documentElement.getAttribute("youtube-wpr"); let s = ''; // Check if the current page is the video watch page. if (isWatchPageURL()) { let watch = document.querySelector("ytd-watch-flexy"); let chat = document.querySelector("ytd-live-chat-frame#chat"); if (watch) { // Determine the state of the chat and video player on the watch page and generate a state string. s += !chat ? 'h0' : (chat.hasAttribute('collapsed') || !document.querySelector('iframe#chatframe')) ? 'h1' : 'h2'; s += watch.hasAttribute('is-two-columns_') ? 's' : 'S'; s += watch.hasAttribute('fullscreen') ? 'F' : 'f'; s += watch.hasAttribute('theater') ? 'T' : 't'; } } // Update the reflected state if it has changed. if (s !== youtubeWpr) { document.documentElement.setAttribute("youtube-wpr", s); } } // Function to reflect changes in specific attributes of monitored elements. async function reflect(nodeName, attrNames, forced) { await Promise.resolve(); if (!forced) { let skip = true; for (const attrName of attrNames) { if (nodeName === 'ytd-live-chat-frame') { if (attrName === 'collapsed') skip = false; } else if (nodeName === 'ytd-watch-flexy') { if (attrName === 'is-two-columns_') skip = false; else if (attrName === 'fullscreen') skip = false; else if (attrName === 'theater') skip = false; } } if (skip) return; } // Log the mutated element and its attributes. // console.log(nodeName, attrNames); // Call _reflect() to update the reflected state. _reflect(); } // Callback function for the MutationObserver that tracks mutations in monitored elements. function callback(mutationsList) { const attrNames = new Set(); let nodeName = null; for (const mutation of mutationsList) { if (nodeName === null && mutation.target) nodeName = mutation.target.nodeName.toLowerCase(); attrNames.add(mutation.attributeName); } reflect(nodeName, attrNames, false); } function getParent(element) { return element.__shady_native_parentNode || element.__shady_parentNode || element.parentNode; } let lastPageTypeChanged = 0; function chatContainerMutationHandler() { if (Date.now() - lastPageTypeChanged < 800) _reflect(); } // Function to start monitoring an element for mutations. function monitor(element) { if (!element) return; if (monitorWeakSet.has(element)) { return; } monitorWeakSet.add(element); const observer = new MutationObserver(callback); observer.observe(element, { attributes: true }); if (element.id === 'chat') { const parentNode = getParent(element); if (parentNode instanceof Element && parentNode.id === 'chat-container' && !monitorWeakSet.has(parentNode)) { monitorWeakSet.add(parentNode); const observer = new MutationObserver(chatContainerMutationHandler); observer.observe(parentNode, { childList: true, subtree: false }); } } return 1; } let timeout = 0; // Function to monitor relevant elements and update the reflected state. let g = async (forced) => { await Promise.resolve(); let b = 0; b = b | monitor(document.querySelector("ytd-watch-flexy")); b = b | monitor(document.querySelector("ytd-live-chat-frame#chat")); if (b || forced) { _reflect(); } } // let renderId = 0; // Event handler function that triggers when the page finishes navigation or page data updates. let eventHandlerFunc = async (evt) => { checkPageVisibilityChanged = true; timeout = Date.now() + 800; g(1); if (evt.type === 'yt-navigate-finish') { // delay required when page type is changed for #chat (home -> watch). setTimeout(() => { g(1); }, 80); } else if (evt.type === 'yt-page-type-changed') { lastPageTypeChanged = Date.now(); // setTimeout(() => { // if (renderId > 1e9) renderId = 9; // const t = ++renderId; // requestAnimationFrame(() => { // if (t !== renderId) return; // g(1); // }); // }, 180); if (typeof requestIdleCallback === 'function') { requestIdleCallback(() => { g(1); }); } } } let loadState = 0; // Function to initialize the script and start monitoring the page. async function actor() { if (loadState === 0) { if (!document.documentElement.hasAttribute("youtube-wpr")) { loadState = 1; document.documentElement.setAttribute("youtube-wpr", ""); document.addEventListener("yt-navigate-finish", eventHandlerFunc, false); document.addEventListener("yt-page-data-updated", eventHandlerFunc, false); document.addEventListener("yt-page-type-changed", eventHandlerFunc, false); } else { loadState = -1; document.removeEventListener("yt-page-data-fetched", actor, false); return; } } if (loadState === 1) { timeout = Date.now() + 800; // Function to continuously monitor elements and update the reflected state. let pf = () => { g(0); if (Date.now() < timeout) requestAnimationFrame(pf); }; pf(); } } // Event listener that triggers when page data is fetched. document.addEventListener("yt-page-data-fetched", actor, false); // Update after visibility changed (looks like there are bugs due to inactive tab) document.addEventListener('visibilitychange', () => { if (document.visibilityState !== 'visible') return; if (checkPageVisibilityChanged) { checkPageVisibilityChanged = false; setTimeout(() => { g(1); }, 100); requestAnimationFrame(() => { g(1); }); } }, false); })(); }); })({ ResizeObserver }); // Auto skip ads and prevent video autopausing (() => { let popupState = 0; let popupElement = null; const rate = 1; const Promise = (async () => { })().constructor; const PromiseExternal = ((resolve_, reject_) => { const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject }; return class PromiseExternal extends Promise { constructor(cb = h) { super(cb); if (cb === h) { /** @type {(value: any) => void} */ this.resolve = resolve_; /** @type {(reason?: any) => void} */ this.reject = reject_; } } }; })(); const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0); let vload = null; const fastSeekFn = HTMLVideoElement.prototype.fastSeek || null; const addEventListenerFn = HTMLElement.prototype.addEventListener; if (!addEventListenerFn) return; const removeEventListenerFn = HTMLElement.prototype.removeEventListener; if (!removeEventListenerFn) return; const ytPremiumPopupSelector = 'yt-mealbar-promo-renderer.style-scope.ytd-popup-container:not([hidden])'; const DEBUG = 0; const rand = (a, b) => a + Math.random() * (b - a); const log = DEBUG ? console.log.bind(console) : () => 0; //$0.$['dismiss-button'].click() const ytPremiumPopupClose = function () { const popup = document.querySelector(ytPremiumPopupSelector); if (popup instanceof HTMLElement) { if (HTMLElement.prototype.closest.call(popup, '[hidden]')) return; const cnt = insp(popup); const btn = cnt.$ ? cnt.$['dismiss-button'] : 0; if (btn instanceof HTMLElement && HTMLElement.prototype.closest.call(btn, '[hidden]')) return; btn && btn.click(); } } //div.video-ads.ytp-ad-module const clickSkip = function () { // ytp-ad-skip-button const isAdsContainerContainsButton = document.querySelector('.video-ads.ytp-ad-module button'); if (isAdsContainerContainsButton) { const btnFilter = e => HTMLElement.prototype.matches.call(e, ".ytp-ad-overlay-close-button, .ytp-ad-skip-button-modern, .ytp-ad-skip-button") && !HTMLElement.prototype.closest.call(e, '[hidden]'); const btns = [...document.querySelectorAll('.video-ads.ytp-ad-module button[class*="ytp-ad-"]')].filter(btnFilter); console.log('# of ads skip btns', btns.length); if (btns.length !== 1) return; const btn = btns[0]; if (btn instanceof HTMLElement) { btn.click(); } } }; const adsEndHandlerHolder = function (evt) { adsEndHandler && adsEndHandler(evt); } let adsEndHandler = null; const videoPlayingHandler = async function (evt) { try { if (!evt || !evt.target || !evt.isTrusted || !(evt instanceof Event)) return; const video = evt.target; const checkPopup = popupState === 1; popupState = 0; const popupElementValue = popupElement; popupElement = null; if (video.duration < 0.8) return; await vload.then(); if (!video.isConnected) return; const ytplayer = HTMLElement.prototype.closest.call(video, 'ytd-player, ytmusic-player'); if (!ytplayer || !ytplayer.is) return; const ytplayerCnt = insp(ytplayer); const player_ = await (ytplayerCnt.player_ || ytplayer.player_ || ytplayerCnt.playerApi || ytplayer.playerApi || 0); if (!player_) return; if (typeof ytplayerCnt.getPlayer === 'function' && !ytplayerCnt.getPlayer()) { await new Promise(r => setTimeout(r, 40)); } const playerController = await ytplayerCnt.getPlayer() || player_; if (!video.isConnected) return; if ('getPresentingPlayerType' in playerController && 'getDuration' in playerController) { const ppType = await playerController.getPresentingPlayerType(); log('m02a', ppType); if (ppType === 1 || typeof ppType !== 'number') return; // ads shall be ppType === 2 // const progressState = player_.getProgressState(); // log('m02b', progressState); // if(!progressState) return; // const q = progressState.duration; // if (popupState === 1) console.debug('m05b:ytPremiumPopup', document.querySelector(ytPremiumPopupSelector)) const q = video.duration; const ytDuration = await playerController.getDuration(); log('m02c', q, ytDuration, Math.abs(ytDuration - q)); if (q > 0.8 && ytDuration > 2.5 && Math.abs(ytDuration - q) > 1.4) { try { log('m02s', 'fastSeek', q); video.muted = true; const w = Math.round(rand(582, 637) * rate); const sq = q - w / 1000; adsEndHandler = null; const expired = Date.now() + 968; removeEventListenerFn.call(video, 'ended', adsEndHandlerHolder, false); removeEventListenerFn.call(video, 'suspend', adsEndHandlerHolder, false); removeEventListenerFn.call(video, 'durationchange', adsEndHandlerHolder, false); addEventListenerFn.call(video, 'ended', adsEndHandlerHolder, false); addEventListenerFn.call(video, 'suspend', adsEndHandlerHolder, false); addEventListenerFn.call(video, 'durationchange', adsEndHandlerHolder, false); adsEndHandler = async function (evt) { adsEndHandler = null; removeEventListenerFn.call(video, 'ended', adsEndHandlerHolder, false); removeEventListenerFn.call(video, 'suspend', adsEndHandlerHolder, false); removeEventListenerFn.call(video, 'durationchange', adsEndHandlerHolder, false); if (Date.now() < expired) { const delay = Math.round(rand(92, 117)); await new Promise(r => setTimeout(r, delay)); Promise.resolve().then(() => { clickSkip(); }).catch(console.warn); checkPopup && Promise.resolve().then(() => { const currentPopup = document.querySelector(ytPremiumPopupSelector); if (popupElementValue ? currentPopup === popupElementValue : currentPopup) { ytPremiumPopupClose(); } }).catch(console.warn); } }; if (fastSeekFn) fastSeekFn.call(video, sq); else video.currentTime = sq; } catch (e) { console.warn(e); } } } } catch (e) { console.warn(e); } }; document.addEventListener('loadedmetadata', async function (evt) { try { if (!evt || !evt.target || !evt.isTrusted || !(evt instanceof Event)) return; const video = evt.target; if (video.nodeName !== "VIDEO") return; if (video.duration < 0.8) return; if (!video.matches('.video-stream.html5-main-video')) return; popupState = 0; vload = new PromiseExternal(); popupElement = document.querySelector(ytPremiumPopupSelector); removeEventListenerFn.call(video, 'playing', videoPlayingHandler, { passive: true, capture: false }); addEventListenerFn.call(video, 'playing', videoPlayingHandler, { passive: true, capture: false }); popupState = 1; let trial = 6; await new Promise(resolve => { let io = new IntersectionObserver(entries => { if (trial-- <= 0 || (entries && entries.length >= 1 && video.matches('ytd-player video, ytmusic-player video'))) { resolve(); io.disconnect(); io = null; } }); io.observe(video); }); vload.resolve(); } catch (e) { console.warn(e); } }, true); })(); Object.defineProperties(document, { /*'hidden': {value: false},*/ 'webkitHidden': {value: false}, 'visibilityState': {value: 'visible'}, 'webkitVisibilityState': {value: 'visible'} }); setInterval(function(){ document.dispatchEvent( new KeyboardEvent( 'keyup', { bubbles: true, cancelable: true, keyCode: 143, which: 143 } ) ); }, 60000);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址