YouTube EXPERIMENT_FLAGS Tamer

Adjust EXPERIMENT_FLAGS

  1. // ==UserScript==
  2. // @name YouTube EXPERIMENT_FLAGS Tamer
  3. // @namespace UserScripts
  4. // @match https://www.youtube.com/*
  5. // @version 1.6.12
  6. // @license MIT
  7. // @author CY Fung
  8. // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/yt-engine.png
  9. // @description Adjust EXPERIMENT_FLAGS
  10. // @grant none
  11. // @unwrap
  12. // @run-at document-start
  13. // @allFrames true
  14. // @inject-into page
  15. // @require https://update.greatest.deepsurf.us/scripts/475632/1361351/ytConfigHacks.js
  16. // ==/UserScript==
  17.  
  18. (() => {
  19.  
  20. // Purpose 1: Remove Obsolete Flags
  21. // Purpose 2: Remove Flags bring no visual difference
  22. // Purpose 3: Enable Flags bring performance boost
  23.  
  24. const DISABLE_CINEMATICS = false; // standard design
  25. const NO_SerializedExperiment = false;
  26. const KEEP_PLAYER_QUALITY_STICKY = true; // see https://greatest.deepsurf.us/scripts/471033/
  27. const DISABLE_serializedExperimentIds = true;
  28. const DISABLE_serializedExperimentFlags = true;
  29. const IGNORE_VIDEO_SOURCE_RELATED = true;
  30. const NO_REFRESH = true;
  31. const ENABLE_MINOR_CHAT_FEATURE_UPGRADE = true;
  32. const ENABLE_EMOJI_PICKER_NEW_STYLE = false;
  33. const ENABLE_BADGE_STYLE = false;
  34. const NO_DESKTOP_DELAY_PLAYER_RESIZING = false;
  35. const NO_ANIMATED_LIKE = false;
  36. const KEEP_MIDDLEWAVE = true;
  37. const NO_CINEMATIC_LIGHTING_LABEL = false; // set true to show "Ambient Mode" label instead of "Cinematic lighting" Label
  38. const KEEP_unified_player = true; // for YouTube Audio Only
  39.  
  40. const SET_POLYMER_FLAGS = true;
  41. const FLAG_STRATEGY_01 = true; // ignore ads related flags
  42.  
  43. const FLAG_STRATEGY_02 = true; // ignore player related flags
  44.  
  45. const FLAG_STRATEGY_03 = true; // ignore adblock related flags
  46.  
  47. const FLAG_STRATEGY_20240413 = true; // ignore adblock related flags
  48.  
  49. const FLAG_STRATEGY_20240503 = true; // AD FLAG
  50.  
  51. const NO_DEBUG_FLAG = true;
  52.  
  53. const FLAG_SKIP_CHAT_BUTTON = true;
  54.  
  55. const ALLOW_FLAGS_202404 = true;
  56.  
  57. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  58.  
  59. const ENABLE_EXPERIMENT_FLAGS_MAINTAIN_STABLE_LIST = {
  60. defaultValue: true, // performance boost
  61. useExternal: () => typeof localStorage.EXPERIMENT_FLAGS_MAINTAIN_STABLE_LIST !== 'undefined',
  62. externalValue: () => (+localStorage.EXPERIMENT_FLAGS_MAINTAIN_STABLE_LIST ? true : false)
  63. };
  64. const ENABLE_EXPERIMENT_FLAGS_MAINTAIN_REUSE_COMPONENTS = {
  65. defaultValue: true, // not sure
  66. useExternal: () => typeof localStorage.EXPERIMENT_FLAGS_MAINTAIN_REUSE_COMPONENTS !== 'undefined',
  67. externalValue: () => (+localStorage.EXPERIMENT_FLAGS_MAINTAIN_REUSE_COMPONENTS ? true : false)
  68. };
  69. const ENABLE_EXPERIMENT_FLAGS_DEFER_DETACH = {
  70. defaultValue: true, // not sure
  71. useExternal: () => typeof localStorage.ENABLE_EXPERIMENT_FLAGS_DEFER_DETACH !== 'undefined',
  72. externalValue: () => (+localStorage.ENABLE_EXPERIMENT_FLAGS_DEFER_DETACH ? true : false)
  73. };
  74.  
  75. const ENABLE_EXPERIMENT_FLAGS_NO_AUTOPLAY_TOGGLE = {
  76. defaultValue: false, // true to remove autoplay toggle button
  77. useExternal: () => typeof localStorage.ENABLE_EXPERIMENT_FLAGS_NO_AUTOPLAY_TOGGLE !== 'undefined',
  78. externalValue: () => (+localStorage.ENABLE_EXPERIMENT_FLAGS_NO_AUTOPLAY_TOGGLE ? true : false)
  79. };
  80.  
  81. const ALLOW_ALL_LIVE_CHATS_FLAGS = false;
  82.  
  83. const USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET = false;
  84.  
  85. const COMMENTS_NO_DELAY = true;
  86.  
  87. const SPACEBAR_CONTROL = -1; // 0 - only scroll down; 1 - global pause; 2 - speed control pause;
  88. // -1 = by pass
  89.  
  90. const ALLOW_THEATER_PLAYER_SHORTCUT_KEY_T = true;
  91.  
  92. const USE_byPassConditionAnalyzer = false;
  93.  
  94. // ----------------------------- FOR FINDING OUT THE NEW FLAG -------------------------------
  95. const byPassConditionAnalyzer = (() => {
  96.  
  97. // This is to find the flags disabled by this script would cause your issue.
  98. // Goal: find the flag name to whitelist
  99.  
  100. const testFn = (key, isVideoPlayerParams) => {
  101.  
  102. const kl = key.length;
  103. const kl7 = kl % 7;
  104. const kl5 = kl % 5;
  105. const kl3 = kl % 3;
  106. const kl2 = kl % 2;
  107.  
  108.  
  109. // ture for by pass
  110. const byConditions = [
  111. !kl2,
  112. kl3 <= 1,
  113. kl5 >= 3,
  114. kl7 >= 4,
  115. kl >= 20,
  116. kl <= 40,
  117. [
  118. "clean_up_manual_attribution_header",
  119. "empty_attributed_string_killswitch",
  120. "enable_profile_cards_cairo_updates",
  121. "enable_teaser_framework_web_client",
  122. "enable_tectonic_ad_ux_for_halftime",
  123. "enable_web_shorts_save_audio_pivot",
  124. "kevlar_clear_duplicate_pref_cookie",
  125. "kevlar_disable_background_prefetch",
  126. "kevlar_transcript_engagement_panel",
  127. "kevlar_watch_flexy_theater_manager",
  128. "mdx_load_cast_api_bootstrap_script",
  129. "web_collab_playlist_thumbnail_size",
  130. "web_fix_back_button_player_loading",
  131. "web_fix_dynamic_metadata_diacritic",
  132. "web_kevlar_enable_adaptive_signals",
  133. "web_move_autoplay_video_under_chip",
  134. "web_player_small_hbp_settings_menu",
  135. "web_rendererstamper_event_listener",
  136. "web_shorts_skip_loading_same_index",
  137. "web_shorts_suggested_action_no_bvm",
  138. "web_use_updated_icon_for_oac_badge",
  139. "wiz_prevent_watched_double_logging"
  140. ]
  141. ];
  142.  
  143. // const byConditions = [
  144. // !kl2,
  145. // kl3 <= 1,
  146. // kl5 >= 3,
  147. // kl7 >= 4,
  148. // kl >= 20,
  149. // kl <= 40,
  150. // [
  151. // "clean_up_manual_attribution_header",
  152. // "empty_attributed_string_killswitch",
  153. // "enable_profile_cards_cairo_updates",
  154. // "enable_teaser_framework_web_client",
  155. // "enable_tectonic_ad_ux_for_halftime",
  156. // "enable_web_shorts_save_audio_pivot",
  157. // "kevlar_clear_duplicate_pref_cookie",
  158. // "kevlar_disable_background_prefetch",
  159. // "kevlar_transcript_engagement_panel",
  160. // "kevlar_watch_flexy_theater_manager",
  161. // "mdx_load_cast_api_bootstrap_script",
  162. // "web_collab_playlist_thumbnail_size",
  163. // "web_fix_back_button_player_loading",
  164. // "web_fix_dynamic_metadata_diacritic",
  165. // "web_kevlar_enable_adaptive_signals",
  166. // "web_move_autoplay_video_under_chip",
  167. // "web_player_small_hbp_settings_menu",
  168. // "web_rendererstamper_event_listener",
  169. // "web_shorts_skip_loading_same_index",
  170. // "web_shorts_suggested_action_no_bvm",
  171. // "web_use_updated_icon_for_oac_badge",
  172. // "wiz_prevent_watched_double_logging"
  173. // ]
  174. // ];
  175.  
  176. return byConditions;
  177.  
  178. };
  179.  
  180. let u = 0;
  181. let cache1 = new Set();
  182. let cache2 = new Set();
  183.  
  184. const disp = () => {
  185. const q = cache1.size < 50 ? [...cache1] : [];
  186. const a = [];
  187. const b = [];
  188. for (const m of q) {
  189. if (cache2.has(m)) b.push(m); else a.push(m);
  190. }
  191. console.log('[yt-flags-tamer]', 'filtered keys {eflags}', a.length, a);
  192. console.log('[yt-flags-tamer]', 'filtered keys {vflags}', b.length, b);
  193. }
  194.  
  195. const res = {
  196.  
  197. testFn_: (key, isVideoPlayerParams) => {
  198.  
  199. if (!u) {
  200. u = 1;
  201. u = setTimeout(disp, 400);
  202. }
  203. let q = testFn(key, isVideoPlayerParams).every(e => {
  204.  
  205. if (typeof e === 'object' && Symbol.iterator in Object(e)) {
  206. return e.includes(key);
  207. } else if (typeof e === 'string') {
  208. return e.includes(key);
  209. } else {
  210. return !!e
  211. }
  212.  
  213. });
  214. if (q) {
  215.  
  216. cache1.add(key);
  217. return true;
  218.  
  219. }
  220. return false;
  221.  
  222.  
  223. }
  224.  
  225. }
  226.  
  227.  
  228. return res;
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235. })();
  236. // ----------------------------- FOR FINDING OUT THE NEW FLAG -------------------------------
  237.  
  238. // TBC
  239. // kevlar_tuner_should_always_use_device_pixel_ratio
  240. // kevlar_tuner_should_clamp_device_pixel_ratio
  241. // kevlar_tuner_clamp_device_pixel_ratio
  242. // kevlar_tuner_should_use_thumbnail_factor
  243. // kevlar_tuner_thumbnail_factor
  244. // kevlar_tuner_min_thumbnail_quality
  245. // kevlar_tuner_max_thumbnail_quality
  246.  
  247. // kevlar_tuner_should_test_visibility_time_between_jobs
  248. // kevlar_tuner_visibility_time_between_jobs_ms
  249.  
  250. // kevlar_tuner_default_comments_delay
  251. // kevlar_tuner_run_default_comments_delay
  252.  
  253. // cinematic feature is no longer an experimental feature.
  254. // It has been officially implemented.
  255. // To disable cinematics, the user shall use other userscripts or just turn off the option in the video options.
  256.  
  257. const getSettingValue = (fm) => fm.useExternal() ? fm.externalValue() : fm.defaultValue;
  258.  
  259. const win = this instanceof Window ? this : window;
  260.  
  261. // Create a unique key for the script and check if it is already running
  262. const hkey_script = 'jmimcvowrlzl';
  263. if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  264. win[hkey_script] = true;
  265.  
  266. /** @type {globalThis.PromiseConstructor} */
  267. const Promise = ((async () => { })()).constructor;
  268.  
  269. let isMainWindow = false;
  270. const mzFlagDetected1 = new Set();
  271. const mzFlagDetected2 = new Set();
  272. let zPlayerKevlar = false;
  273. try {
  274. isMainWindow = window.document === window.top.document
  275. } catch (e) { }
  276.  
  277. const fOperAccept = Symbol();
  278. const fOperReject = Symbol();
  279.  
  280. // h5 flags
  281. const fOperAcceptList = new Set([
  282.  
  283. ...(NO_CINEMATIC_LIGHTING_LABEL ? [
  284. 'web_player_use_cinematic_label', // fallback
  285. 'web_player_use_cinematic_label_0', // fallback
  286. 'web_player_use_cinematic_label_1', // fallback
  287. 'web_player_use_cinematic_label_2',
  288. 'web_player_use_cinematic_label_3', // fallback
  289. ] : []),
  290.  
  291. ...(FLAG_STRATEGY_03 ? [
  292. // do it with your separate script please
  293. 'ab_pl_man', // https://www.uedbox.com/post/69238/
  294. 'ab_fk_sk_cl', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  295. 'ab_det_apb_b',
  296. 'ab_det_el_h',
  297. 'ab_det_fet_wr',
  298. 'ab_det_fet_wr_en',
  299. 'ab_det_gen_re',
  300. 'web_enable_ab_rsp_cl',
  301. 'enable_ab_rp_int',
  302. 'enable_ab_report_on_errorscreen',
  303. 'enable_pl_r_si_fa',
  304. 'ab_det_sc_inj_enf',
  305. 'service_worker_enabled', // https://gist.github.com/BrokenGabe/51d55a11c2090d9402e40f12a6ece275
  306. 'ab_deg_unex_thr', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  307. 'ab_net_tp_e', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  308. 'ad_net_pb_ab', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  309. 'ab_mis_log_err', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  310. 'ad_net_pb_pbp',
  311.  
  312. 'ab_det_sc_inj',
  313. 'ab_det_sc_inj_val',
  314. 'disable_enf_isd',
  315. 'ks_det_gpbl',
  316. 'ks_get_o_pp',
  317. 'ab_deg_unex_thr',
  318. 'enable_pl_r_si_fa',
  319. 'debug_sk_em_precheck',
  320.  
  321. ] : []),
  322.  
  323.  
  324.  
  325. ...(FLAG_STRATEGY_01 ? [
  326. 'web_player_defer_modules',
  327. 'html5_defer_modules_on_ads_only',
  328. 'web_player_defer_ad',
  329. 'disable_defer_admodule_on_advertiser_video',
  330. 'html5_onesie_defer_content_loader_ms',
  331. 'html5_defer_fetch_att_ms',
  332. 'embeds_web_enable_defer_loading_remote_js',
  333. ] : []),
  334.  
  335. ...(KEEP_MIDDLEWAVE ? [
  336. 'web_player_entities_middleware'
  337. ] : []),
  338.  
  339.  
  340. 'web_settings_menu_icons',
  341. // see https://github.com/cyfung1031/userscript-supports/issues/27
  342. // see https://greatest.deepsurf.us/scripts/470428/discussions/216363
  343.  
  344.  
  345. // 'disable_new_pause_state3',
  346. // 'enable_cast_on_music_web',
  347. // 'gcf_config_store_enabled',
  348. // 'gel_queue_timeout_max_ms',
  349. // 'network_polling_interval',
  350. 'player_doubletap_to_seek',
  351. // 'polymer_bad_build_labels',
  352. // 'skip_invalid_ytcsi_ticks',
  353. // 'use_player_cue_range_set',
  354. // 'woffle_used_state_report',
  355.  
  356. ]);
  357.  
  358. const fOperMapFn = (o) => new Map(Object.entries({
  359. // 1 true 2 false 3
  360.  
  361. ...((o.no_autoplay_toggle !== true) ? {
  362.  
  363. // 'player_allow_autonav_after_playlist',
  364. 'web_player_autonav_toggle_always_listen': 1,
  365. // 'web_player_offline_playlist_auto_refresh',
  366.  
  367. // 'allow_live_autoplay',
  368. // 'allow_poltergust_autoplay',
  369. // 'autoplay_time',
  370. // 'autoplay_time_for_fullscreen',
  371. // 'autoplay_time_for_music_content',
  372. 'client_respect_autoplay_switch_button_renderer': 1,
  373. // 'embeds_enable_muted_autoplay',
  374. // 'embeds_web_enable_autoplay_not_supported_logging_fix',
  375. // 'embeds_web_enable_log_splay_as_autoplay',
  376. // 'embeds_web_enable_mobile_autoplay',
  377. // 'html5_autoplay_default_quality_cap',
  378. // 'mweb_muted_autoplay_animation',
  379.  
  380. // 'html5_player_autonav_logging',
  381. // 'web_player_always_enable_auto_translation',
  382. // 'web_player_autonav_empty_suggestions_fix',
  383. // 'web_player_autonav_use_server_provided_state',
  384. 'web_player_decouple_autonav': 1,
  385. 'web_player_move_autonav_toggle': 1,
  386.  
  387. } : {}),
  388.  
  389. ...(IGNORE_VIDEO_SOURCE_RELATED ? {
  390.  
  391. 'html5_live_use_alternate_bandwidth_window_sizes': 1,
  392. 'html5_live_ultra_low_latency_bandwidth_window': 1,
  393. 'html5_live_low_latency_bandwidth_window': 1,
  394. 'html5_live_normal_latency_bandwidth_window': 1,
  395. // 'html5_skip_slow_ad_delay_ms': 1,
  396. 'html5_player_preload_ad_fix': 1,
  397. // if (key.includes('_ad_') || key.includes('_ads_')) {
  398. 'html5_ssdai_adfetch_dynamic_timeout_ms': 2,
  399. 'html5_log_ssdai_fallback_ads': 2,
  400. 'html5_deprecate_adservice': 2,
  401. // !key.includes('deprecat')) keep = true;
  402.  
  403.  
  404. // if (key.startsWith('enable_h5_player_ad_block_')) keep = false;
  405. 'fix_h5_toggle_button_a11y': 1,
  406. 'h5_companion_enable_adcpn_macro_substitution_for_click_pings': 2,
  407. 'h5_enable_generic_error_logging_event': 2,
  408. 'h5_enable_unified_csi_preroll': 1,
  409. 'h5_reset_cache_and_filter_before_update_masthead': 1,
  410. 'web_player_enable_premium_hbr_in_h5_api': 1,
  411. // !key.includes('deprecat')) keep = true;
  412.  
  413. } : {}),
  414.  
  415.  
  416. ...(KEEP_PLAYER_QUALITY_STICKY ? {
  417.  
  418. html5_onesie_sticky_server_side: 2,
  419. html5_perf_cap_override_sticky: 1,
  420. html5_ustreamer_cap_override_sticky: 1,
  421. html5_exponential_memory_for_sticky: 1
  422.  
  423. } : {}),
  424.  
  425.  
  426. 'html5_streaming_xhr_time_based_consolidation_ms': 1,
  427. 'html5_bypass_contention_secs': 1,
  428.  
  429. 'vp9_drm_live': 1,
  430. 'html5_log_rebuffer_reason': 2,
  431. 'html5_enable_audio_track_log': 2,
  432.  
  433.  
  434. 'html5_safari_desktop_eme_min_version': 1,
  435.  
  436. 'html5_disable_av1': 1,
  437. 'html5_disable_av1_hdr': 1,
  438. 'html5_disable_hfr_when_vp9_encrypted_2k4k_unsupported': 1,
  439. 'html5_account_onesie_format_selection_during_format_filter': 1,
  440. 'html5_prefer_hbr_vp9_over_av1': 1,
  441.  
  442. ...(!DISABLE_CINEMATICS ? {
  443. 'web_cinematic_watch_settings': 1
  444. } : {}),
  445.  
  446. 'html5_apply_start_time_within_ads_for_ssdai_transitions': 2,
  447. 'html5_enable_ads_client_monitoring_log_tv': 2,
  448. 'html5_ignore_interruptive_ads_for_server_stitched': 1,
  449.  
  450. 'html5_no_video_to_ad_on_preroll': 1,
  451. 'html5_no_video_to_ad_on_preroll_reset': 1,
  452. 'html5_rebase_video_to_ad_timeline': 1,
  453. 'html5_report_slow_ads_as_error': 1,
  454.  
  455. 'html5_default_ad_gain': 1, // just keep
  456. 'html5_min_startup_buffered_ad_media_duration_secs': 1, // just keep
  457.  
  458. 'html5_skip_slow_ad_delay_ms': 7,
  459. 'check_navigator_accuracy_timeout_ms': 8,
  460. 'html5_ad_timeout_ms': 8,
  461. 'html5_ads_preroll_lock_timeout_delay_ms': 9,
  462. 'html5_slow_start_timeout_delay_ms': 8,
  463. 'variable_buffer_timeout_ms': 9,
  464.  
  465. 'h5_expr_b9Nkc': 1,
  466.  
  467. }));
  468.  
  469. var fOperMap;
  470.  
  471. const valur = (value, k) => {
  472. if (+value === 0) value = k;
  473. else if (+value > +k) value = k;
  474. return value;
  475. }
  476.  
  477. function fOper(key, value) {
  478.  
  479. if (fOperAcceptList.has(key)) return fOperAccept;
  480. if (USE_byPassConditionAnalyzer && byPassConditionAnalyzer.testFn_(key, true)) return fOperAccept;
  481. if (key.length === 22 || key.length === 27 || key.length === 32) {
  482.  
  483. if (SPACEBAR_CONTROL < 0) {
  484.  
  485. if (key === 'disable_space_scroll_fix' || key === 'global_spacebar_pause' || key === 'web_speedmaster_spacebar_control') {
  486. return fOperAccept;
  487. }
  488. if (key.includes('speedmaster')) return fOperAccept;
  489. }
  490.  
  491. if (SPACEBAR_CONTROL === 2 && key.includes('speedmaster')) {
  492. return fOperAccept;
  493. }
  494.  
  495. }
  496. // if(key.length < 30)continue;
  497. // const kl = key.length;
  498.  
  499. let keep = false;
  500. let nv = undefined;
  501.  
  502. const no_autoplay_toggle = ENABLE_EXPERIMENT_FLAGS_NO_AUTOPLAY_TOGGLE.currentValue;
  503.  
  504. fOperMap = fOperMap || fOperMapFn({ no_autoplay_toggle });
  505.  
  506. const fm1 = fOperMap.get(key);
  507.  
  508. switch (fm1) {
  509. case 1:
  510. keep = true;
  511. break;
  512. case 2:
  513. keep = false;
  514. break;
  515. case 7:
  516. const kv = typeof value === 'string' && +value > 2;
  517. keep = kv;
  518. if (kv && +value > 4) nv = '4';
  519. break;
  520. case 8:
  521. nv = valur(value, '4');
  522. keep = true;
  523. break;
  524. case 9:
  525. keep = false;
  526. break;
  527. default:
  528.  
  529. if (FLAG_STRATEGY_20240413 && key.includes('network')) keep = true;
  530. else if (FLAG_STRATEGY_20240413 && key.includes('less')) keep = true;
  531. else if (FLAG_STRATEGY_20240413 && key.includes('latency')) keep = true;
  532. else if (FLAG_STRATEGY_20240413 && key.includes('slow')) keep = true;
  533. else if (FLAG_STRATEGY_20240413 && key.includes('steam')) keep = true;
  534. else if (key.includes('deprecat')) {
  535. keep = false;
  536. } else if (IGNORE_VIDEO_SOURCE_RELATED && key.includes('html5_') && !key.includes('_ad_') && !key.includes('_ads_')) {
  537. keep = true;
  538. } else if (IGNORE_VIDEO_SOURCE_RELATED && key.includes('h5_')) {
  539. keep = true;
  540. } else if (key.includes('_timeout') && typeof value === 'string') {
  541. if (+value > 3000) nv = '3000';
  542. keep = true;
  543. } else if (KEEP_PLAYER_QUALITY_STICKY && key.includes('_sticky')) {
  544. keep = true;
  545. } else if (key.startsWith('h5_expr_')) {
  546. // by userscript
  547. keep = true;
  548. }
  549. }
  550.  
  551. if (!keep) {
  552. return fOperReject;
  553. // vRes.delete(key);
  554. } else if (nv !== undefined && nv !== value) {
  555. return nv;
  556. // vRes.set(key, nv)
  557. } else {
  558. return fOperAccept;
  559. }
  560.  
  561. }
  562. function deSerialized(str, fOper) {
  563.  
  564. const map = new Map();
  565. let start = 0;
  566.  
  567. while (start < str.length) {
  568. // Find the next '&' or the end of the string
  569. const nextAmpersand = str.indexOf('&', start);
  570. const end = nextAmpersand === -1 ? str.length : nextAmpersand;
  571.  
  572. // Extract the key-value pair
  573. const equalsSign = str.indexOf('=', start);
  574. if (equalsSign !== -1 && equalsSign < end) {
  575. const key = str.substring(start, equalsSign);
  576. const value = str.substring(equalsSign + 1, end);
  577.  
  578. const r = fOper(key, value);
  579. if (typeof r !== 'symbol') {
  580. map.set(key, r)
  581. } else if (r === fOperAccept) {
  582. map.set(key, value);
  583. }
  584.  
  585. }
  586.  
  587. // Move to the next key-value pair
  588. start = end + 1;
  589. }
  590.  
  591. map.toString = function () {
  592. const res = new Array(map.size);
  593. let i = 0;
  594. this.forEach((value, key) => {
  595. res[i++] = `${key}=${value}`;
  596. });
  597. return res.join('&');
  598. }
  599. return map;
  600. }
  601.  
  602. function fixSerializedExperiment(conf) {
  603.  
  604. const supportAV1 = window.MediaSource.isTypeSupported('video/webm; codecs=av01.0.05M.08');
  605. const supportVP9 = window.MediaSource.isTypeSupported('video/webm; codecs=vp09.01.20.08.01.01.01.01.00');
  606.  
  607. if (DISABLE_serializedExperimentIds && typeof conf.serializedExperimentIds === 'string') {
  608. let ids = conf.serializedExperimentIds.split(',');
  609. let newIds = [];
  610. for (const id of ids) {
  611. let keep = false;
  612. if (keep) {
  613. newIds.push(id);
  614. }
  615. }
  616. conf.serializedExperimentIds = newIds.join(',');
  617. }
  618.  
  619. const mez = (mRes) => {
  620.  
  621. mRes.set('html5_disable_low_pipeline', 'false');
  622. mRes.set('html5_min_startup_buffered_ad_media_duration_secs', '0')
  623.  
  624. if (supportAV1 === false && localStorage['yt-player-av1-pref'] === '-1') {
  625.  
  626. mRes.set('html5_disable_av1', 'true');
  627. mRes.set('html5_disable_av1_hdr', 'true');
  628. mRes.set('html5_prefer_hbr_vp9_over_av1', 'true');
  629.  
  630. } else if (supportAV1 === true && supportVP9 === true && localStorage['yt-player-av1-pref'] === '8192') {
  631.  
  632. mRes.set('html5_disable_av1', 'false');
  633. mRes.set('html5_disable_av1_hdr', 'false');
  634. mRes.set('html5_prefer_hbr_vp9_over_av1', 'false');
  635. }
  636.  
  637.  
  638. // html5_perf_cap_override_sticky = true;
  639. // html5_perserve_av1_perf_cap = true;
  640.  
  641.  
  642. mRes.set('html5_enable_server_format_filter', 'true')
  643. mRes.set('html5_use_ump', 'true')
  644.  
  645. mRes.set('html5_live_defrag_only_h264_playbacks', 'true')
  646. mRes.set('html5_live_defrag_only_h264_formats', 'true')
  647.  
  648. mRes.set('html5_disable_protected_hdr', 'false')
  649. mRes.set('html5_disable_vp9_encrypted', 'false')
  650. mRes.set('html5_ignore_h264_framerate_cap', 'true')
  651.  
  652. mRes.set('html5_allow_asmjs', 'true')
  653. // mRes.set('html5_defer_modules_on_ads_only', 'true')
  654. mRes.set('html5_use_drm_retry', 'true')
  655. mRes.set('html5_delta_encode_fexp', 'true')
  656. mRes.set('html5_only_send_cas_health_pings', 'true')
  657.  
  658. mRes.set('html5_modify_caption_vss_logging', 'true')
  659. // mRes.set('html5_allow_zero_duration_ads_on_timeline', 'true')
  660. mRes.set('html5_reset_daistate_on_audio_codec_change', 'true')
  661. mRes.set('html5_enable_safari_fairplay', 'true')
  662.  
  663. mRes.set('html5_safari_fairplay_ignore_hdcp', 'true')
  664.  
  665. mRes.set('html5_enable_vp9_fairplay', 'true')
  666. mRes.set('html5_eme_loader_sync', 'true')
  667.  
  668. mRes.set('html5_enable_same_language_id_matching', 'true');
  669. mRes.set('html5_enable_new_hvc_enc', 'true')
  670. mRes.set('html5_enable_ssap', 'true')
  671. mRes.set('html5_enable_short_gapless', 'true')
  672. mRes.set('html5_enable_aac51', 'true')
  673. mRes.set('html5_enable_ssap_entity_id', 'true')
  674.  
  675. mRes.set('html5_high_res_logging_always', 'true')
  676. mRes.set('html5_local_playsinline', 'true')
  677. mRes.set('html5_disable_media_element_loop_on_tv', 'true')
  678. mRes.set('html5_native_audio_track_switching', 'true')
  679.  
  680. mRes.set('html5_format_hybridization', 'true')
  681. mRes.set('html5_disable_encrypted_vp9_live_non_2k_4k', 'false')
  682.  
  683. // mRes.set('html5_default_ad_gain', 'false')
  684. mRes.set('html5_use_sabr_requests_for_debugging', 'false')
  685. // mRes.set('html5_enable_sabr_live_streaming_xhr', 'true')
  686. // mRes.set('html5_sabr_live_ultra_low_latency', 'true')
  687.  
  688. // mRes.set('html5_sabr_live_low_latency', 'true')
  689. // mRes.set('html5_sabr_live', 'true') // sabr_live for audio only
  690. mRes.set('html5_sabr_post_live', 'true')
  691. mRes.set('html5_sabr_premiere', 'true')
  692.  
  693. // mRes.set('html5_enable_sabr_live_streaming_xhr', 'true')
  694. // mRes.set('html5_enable_sabr_live_non_streaming_xhr', 'true')
  695.  
  696. mRes.set('html5_enable_subsegment_readahead_v3', 'true')
  697. mRes.set('html5_ultra_low_latency_subsegment_readahead', 'true')
  698. mRes.set('html5_disable_move_pssh_to_moov', 'true')
  699.  
  700. mRes.set('html5_modern_vp9_mime_type', 'true')
  701.  
  702. }
  703.  
  704. if (DISABLE_serializedExperimentFlags && typeof conf.serializedExperimentFlags === 'string') {
  705. const fg = conf.serializedExperimentFlags;
  706.  
  707. const vRes = deSerialized(fg, fOper);
  708.  
  709. mez(vRes);
  710.  
  711. const kg = vRes.toString();
  712.  
  713. conf.serializedExperimentFlags = kg;
  714.  
  715. }
  716.  
  717. }
  718.  
  719.  
  720. let brc = 1000;
  721.  
  722. if (typeof AbortSignal !== 'undefined') {
  723. document.addEventListener('yt-action', function () {
  724. if (brc > 8) looperFn();
  725. brc = 0;
  726. }, { capture: true, passive: true, once: true });
  727. }
  728.  
  729.  
  730. // yt flags
  731. const cachedSetFn = (o) => {
  732.  
  733. const { use_maintain_stable_list, use_maintain_reuse_components, use_defer_detach } = o;
  734.  
  735. const BY_PASS = [
  736.  
  737. 'enable_profile_cards_on_comments',
  738.  
  739. ... (SPACEBAR_CONTROL < 0 ? [
  740. 'disable_space_scroll_fix',
  741. 'global_spacebar_pause',
  742. 'web_speedmaster_spacebar_control'
  743. ] : []),
  744.  
  745. ...(ALLOW_FLAGS_202404 ? [
  746.  
  747. 'suppress_error_204_logging',
  748. 'use_request_time_ms_header',
  749.  
  750. 'remove_masthead_channel_banner_on_refresh',
  751. 'action_companion_center_align_description',
  752. 'disable_child_node_auto_formatted_strings',
  753. // 'enable_native_bridge_view_saved_playables',
  754. 'enable_shadydom_free_scoped_query_methods',
  755. // 'enable_skippable_ads_for_unplugged_ad_pod',
  756. 'enable_sparkles_web_clickable_description',
  757. 'enable_window_constrained_buy_flow_dialog',
  758. // 'html5_enable_ads_client_monitoring_log_tv',
  759. 'is_part_of_any_user_engagement_experiment',
  760. // 'kevlar_chapters_list_view_seek_by_chapter',
  761. // 'kevlar_enable_shorts_prefetch_in_sequence',
  762. // 'kevlar_resolve_command_for_confirm_dialog',
  763. // 'kevlar_shorts_seedless_retry_initial_load',
  764. // 'live_chat_enable_send_button_in_slow_mode',
  765. // 'live_chat_web_use_emoji_manager_singleton',
  766. 'remove_masthead_channel_banner_on_refresh',
  767. // 'web_deprecate_service_ajax_map_dependency',
  768. 'web_modern_player_settings_quality_bottom',
  769. // 'web_player_always_enable_auto_translation',
  770. // 'web_player_enable_cultural_moment_overlay',
  771. // 'ytidb_fetch_datasync_ids_for_data_cleanup',
  772. 'kevlar_tuner_should_test_reuse_components',
  773.  
  774. 'web_player_ve_conversion_fixes_for_channel_info',
  775. 'web_watch_updated_metadata_server_initial_delay',
  776. // 'trigger_impression_pings_on_view_search_desktop',
  777.  
  778. 'defer_menus',
  779.  
  780. ] : []),
  781.  
  782. ...(FLAG_SKIP_CHAT_BUTTON ? [
  783. 'live_chat_overflow_hide_chat',
  784. 'web_watch_chat_hide_button_killswitch',
  785. ] : []),
  786.  
  787.  
  788. ...(KEEP_unified_player ? [
  789. 'kevlar_unified_player',
  790. 'kevlar_non_watch_unified_player',
  791. ] : []),
  792.  
  793.  
  794.  
  795. ...(FLAG_STRATEGY_03 ? [
  796. // do it with your separate script please
  797. 'ab_pl_man', // https://www.uedbox.com/post/69238/
  798. 'ab_fk_sk_cl', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  799. 'ab_det_apb_b',
  800. 'ab_det_el_h',
  801. 'ab_det_fet_wr',
  802. 'ab_det_fet_wr_en',
  803. 'ab_det_gen_re',
  804. 'web_enable_ab_rsp_cl',
  805. 'enable_ab_rp_int',
  806. 'enable_ab_report_on_errorscreen',
  807. 'enable_pl_r_si_fa',
  808. 'ab_det_sc_inj_enf',
  809. 'service_worker_enabled', // https://gist.github.com/BrokenGabe/51d55a11c2090d9402e40f12a6ece275
  810. 'ab_deg_unex_thr', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  811. 'ab_net_tp_e', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  812. 'ad_net_pb_ab', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  813. 'ab_mis_log_err', // https://www.youtube.com/s/desktop/28b0985e/jsbin/desktop_polymer.vflset/desktop_polymer.js
  814.  
  815. 'ab_det_sc_inj',
  816. 'ab_det_sc_inj_val',
  817. 'disable_enf_isd',
  818. 'ks_det_gpbl',
  819. 'ks_get_o_pp',
  820. 'ab_deg_unex_thr',
  821. 'enable_pl_r_si_fa',
  822. 'debug_sk_em_precheck',
  823.  
  824. ] : []),
  825.  
  826.  
  827. ...(FLAG_STRATEGY_02 ? [
  828. // do it with your separate script please
  829. 'kevlar_client_enable_shorts_player_bootstrap',
  830. 'kevlar_early_popup_close',
  831. 'kevlar_hide_pp_url_param',
  832. 'kevlar_touch_gesture_ves',
  833. 'player_doubletap_to_seek',
  834. 'shorts_controller_retrieve_seedless_sequence',
  835. 'shorts_overlay_reshuffle',
  836. ] : []),
  837.  
  838.  
  839. ...(SET_POLYMER_FLAGS ? [
  840. 'polymer_enable_mdx_queue',
  841. 'polymer_on_demand_shady_dom',
  842. ] : []),
  843.  
  844. ...(FLAG_STRATEGY_01 ? [
  845. 'web_player_defer_modules',
  846. 'html5_defer_modules_on_ads_only',
  847. 'web_player_defer_ad',
  848. 'disable_defer_admodule_on_advertiser_video',
  849. 'html5_onesie_defer_content_loader_ms',
  850. 'html5_defer_fetch_att_ms',
  851. 'embeds_web_enable_defer_loading_remote_js',
  852. ] : []),
  853.  
  854. ...(KEEP_MIDDLEWAVE ? [
  855. 'web_player_entities_middleware'
  856. ] : []),
  857.  
  858. 'desktop_keyboard_capture_keydown_killswitch', // TBC
  859. 'kevlar_autofocus_menu_on_keyboard_nav', // TBC
  860. 'kevlar_keyboard_button_focus', // TBC
  861. 'kevlar_macro_markers_keyboard_shortcut', // required
  862.  
  863. // 'kevlar_appbehavior_attach_startup_tasks'
  864. // 'kevlar_clear_non_displayable_url_params'
  865. 'kevlar_command_handler_formatted_string', // see https://github.com/cyfung1031/userscript-supports/issues/20
  866. 'kevlar_miniplayer_queue_user_activation',
  867. 'kevlar_player_watch_endpoint_navigation',
  868. // 'kevlar_watch_focus_on_engagement_panels'
  869.  
  870. // playlist related flags
  871. "shorts_in_playlists_web",
  872. "live_chat_over_playlist",
  873. "web_amsterdam_playlists",
  874. "browse_next_continuations_migration_playlist",
  875. "desktop_add_to_playlist_renderer_dialog_popup",
  876. "enable_horizontal_list_renderer_scroll_based_on_items_visibility",
  877. "enable_pass_sdc_get_accounts_list",
  878. "enable_programmed_playlist_color_sample",
  879. "enable_programmed_playlist_redesign",
  880. "enable_section_list_scroll_to_item_section_web",
  881. "gda_enable_playlist_download",
  882. "include_autoplay_count_in_playlists",
  883. "kevlar_chapters_list_view_seek_by_chapter",
  884. "kevlar_enable_editable_playlists",
  885. "kevlar_enable_reorderable_playlists",
  886. "kevlar_fix_playlist_continuation",
  887. "kevlar_hide_playlist_playback_status",
  888. "kevlar_lazy_list_resume_for_autofill",
  889. "kevlar_no_autoscroll_on_playlist_hover",
  890. "kevlar_passive_event_listeners",
  891. "kevlar_player_playlist_use_local_index",
  892. "kevlar_playlist_drag_handles",
  893. "kevlar_playlist_use_x_close_button",
  894. "kevlar_rendererstamper_event_listener",
  895. "kevlar_should_maintain_stable_list",
  896. "kevlar_show_playlist_dl_btn",
  897. "music_on_main_open_playlist_recommended_videos_in_miniplayer",
  898. "player_allow_autonav_after_playlist",
  899. "player_enable_playback_playlist_change",
  900. "web_amsterdam_post_mvp_playlists",
  901.  
  902. // not sure
  903. // "check_user_lact_at_prompt_shown_time_on_web",
  904. "clear_user_partitioned_ls",
  905. "desktop_notification_high_priority_ignore_push",
  906. "desktop_notification_set_title_bar",
  907. "enable_first_user_action_csi_logging",
  908. "enable_get_account_switcher_endpoint_on_webfe",
  909. "enable_handles_account_menu_switcher",
  910. "enable_names_handles_account_switcher", // TBC
  911. "enable_pass_sdc_get_accounts_list",
  912. "enable_server_stitched_dai",
  913. "enable_yt_ata_iframe_authuser",
  914. // "fill_single_video_with_notify_to_lasr",
  915. "html5_server_stitched_dai_group",
  916. // "is_part_of_any_user_engagement_experiment",
  917. "kevlar_miniplayer_queue_user_activation",
  918. // "rich_grid_resize_observer",
  919. // "rich_grid_resize_observer_only",
  920.  
  921. 'desktop_add_to_playlist_renderer_dialog_popup',
  922.  
  923. ...(!DISABLE_CINEMATICS ? [
  924.  
  925. 'kevlar_measure_ambient_mode_idle',
  926. 'kevlar_watch_cinematics_invisible',
  927. 'web_cinematic_theater_mode',
  928. 'web_cinematic_fullscreen',
  929.  
  930. 'enable_cinematic_blur_desktop_loading',
  931. 'kevlar_watch_cinematics',
  932. 'web_cinematic_masthead',
  933. 'web_watch_cinematics_preferred_reduced_motion_default_disabled'
  934.  
  935. ] : []),
  936.  
  937.  
  938.  
  939. 'kevlar_rendererstamper_event_listener', // https://github.com/cyfung1031/userscript-supports/issues/11
  940.  
  941.  
  942.  
  943.  
  944. 'live_chat_web_enable_command_handler',
  945. 'live_chat_channel_activity',
  946. 'live_chat_web_input_update',
  947.  
  948. 'live_chat_web_enable_command_handler',
  949.  
  950. ...(ALLOW_ALL_LIVE_CHATS_FLAGS ? [
  951.  
  952. 'live_chat_banner_expansion_fix',
  953. 'live_chat_enable_mod_view',
  954. 'live_chat_enable_qna_banner_overflow_menu_actions',
  955. 'live_chat_enable_qna_channel',
  956. 'live_chat_enable_send_button_in_slow_mode',
  957. 'live_chat_filter_emoji_suggestions',
  958. 'live_chat_increased_min_height',
  959. 'live_chat_over_playlist',
  960. 'live_chat_web_use_emoji_manager_singleton',
  961. 'live_chat_whole_message_clickable',
  962.  
  963. 'live_chat_emoji_picker_toggle_state',
  964. 'live_chat_enable_command_handler_resolver_map',
  965. 'live_chat_enable_controller_extraction',
  966. 'live_chat_enable_rta_manager',
  967. 'live_chat_require_space_for_autocomplete_emoji',
  968. 'live_chat_unclickable_message',
  969.  
  970. ] : []),
  971.  
  972. 'kevlar_rendererstamper_event_listener', // https://github.com/cyfung1031/userscript-supports/issues/11
  973.  
  974. // kevlar_enable_up_arrow - no use
  975. // kevlar_help_use_locale - might use
  976. // kevlar_refresh_gesture - might use
  977. // kevlar_smart_downloads - might use
  978. // kevlar_thumbnail_fluid
  979. 'kevlar_ytb_live_badges',
  980.  
  981. ...(!use_maintain_stable_list ? [
  982. 'kevlar_tuner_should_test_maintain_stable_list',
  983. 'kevlar_should_maintain_stable_list',
  984. 'kevlar_tuner_should_maintain_stable_list', // fallback
  985.  
  986.  
  987. ] : []),
  988.  
  989.  
  990. ...(!use_maintain_reuse_components ? [
  991.  
  992. 'kevlar_tuner_should_test_reuse_components',
  993. 'kevlar_tuner_should_reuse_components',
  994. 'kevlar_should_reuse_components' // fallback
  995.  
  996. ] : []),
  997.  
  998.  
  999. 'kevlar_system_icons',
  1000.  
  1001. // 'kevlar_prefetch_data_augments_network_data' continue;
  1002.  
  1003. // home page / watch page icons
  1004. 'kevlar_three_dot_ink',
  1005. 'kevlar_use_wil_icons',
  1006. 'kevlar_home_skeleton',
  1007.  
  1008. 'kevlar_fluid_touch_scroll',
  1009. 'kevlar_watch_color_update',
  1010. 'kevlar_use_vimio_behavior', // home page - channel icon
  1011.  
  1012. // collapsed meta; no teaser, use latest collapsed meta design
  1013. 'kevlar_structured_description_content_inline',
  1014. 'kevlar_watch_metadata_refresh',
  1015.  
  1016. 'kevlar_watch_js_panel_height', // affect Tabview Youtube
  1017.  
  1018. 'shorts_desktop_watch_while_p2',
  1019. 'web_button_rework',
  1020. 'web_darker_dark_theme_live_chat',
  1021. 'web_darker_dark_theme', // it also affect cinemtaics
  1022.  
  1023. // modern menu
  1024. 'web_button_rework_with_live',
  1025. 'web_fix_fine_scrubbing_drag',
  1026.  
  1027. // full screen -buggy
  1028. 'external_fullscreen',
  1029.  
  1030. // minimize menu
  1031. 'web_modern_buttons',
  1032. 'web_modern_dialogs',
  1033.  
  1034. // Tabview Youtube - multiline transcript
  1035. 'enable_mixed_direction_formatted_strings',
  1036.  
  1037. // Notification Menu
  1038. "kevlar_service_command_check",
  1039.  
  1040. // Live ChatRoom Visibility
  1041. "live_chat_cow_visibility_set_up",
  1042.  
  1043. 'enable_unknown_lact_fix_on_html5',
  1044.  
  1045.  
  1046.  
  1047.  
  1048. 'live_chat_chunk_across_update_interval',
  1049.  
  1050. 'enable_native_live_chat_on_kevlar',
  1051.  
  1052. 'live_chat_author_name_color_usernames',
  1053. 'live_chat_seed_color_usernames',
  1054. 'live_chat_colored_usernames',
  1055. 'live_chat_simple_color_usernames',
  1056. 'web_button_rework_with_live',
  1057. 'live_chat_hide_avatars',
  1058. 'live_chat_enable_qna_replay',
  1059. 'live_chat_aggregation',
  1060. 'live_chat_web_use_emoji_manager_singleton',
  1061. 'enable_docked_chat_messages',
  1062. 'live_chat_taller_emoji_picker',
  1063. 'live_chat_emoji_picker_restyle',
  1064. 'live_chat_emoji_picker_restyle_remain_open_on_send',
  1065. 'live_chat_web_input_update',
  1066. 'live_chat_enable_send_button_in_slow_mode',
  1067.  
  1068. 'kevlar_watch_metadata_refresh_no_old_primary_data',
  1069. // 'kevlar_watch_metadata_refresh_no_old_secondary_data', // for Tabview Youtube
  1070. 'enable_web_cosmetic_refresh_hashtag_page',
  1071. 'kevlar_watch_metadata_refresh_description_lines',
  1072.  
  1073.  
  1074.  
  1075.  
  1076. 'enable_service_ajax_csn',
  1077.  
  1078. 'kevlar_use_vimio_behavior',
  1079.  
  1080. 'web_use_cache_for_image_fallback',
  1081. 'kevlar_woffle_fallback_image',
  1082. 'yt_img_shadow_trigger_show_on_visible',
  1083. 'kevlar_thumbnail_bg',
  1084. 'web_rounded_thumbnails',
  1085.  
  1086.  
  1087.  
  1088. 'kevlar_rendererstamper_event_listener',
  1089.  
  1090. 'dialog_behavior_no_tap_killswitch',
  1091.  
  1092. 'handle_service_request_actions',
  1093.  
  1094. 'live_chat_whole_message_clickable',
  1095.  
  1096. 'live_chat_require_space_for_autocomplete_emoji',
  1097.  
  1098. 'kevlar_keyboard_button_focus',
  1099.  
  1100. 'live_chat_emoji_picker_toggle_state',
  1101. 'super_sticker_emoji_picker_category_button_icon_filled',
  1102. 'enable_super_chat_buy_flow_revamp_web',
  1103.  
  1104.  
  1105. 'web_modern_buttons',
  1106.  
  1107.  
  1108. 'web_modern_dialogs',
  1109. 'live_chat_disable_chat_feed_animation',
  1110. 'live_chat_overflow_hide_chat',
  1111. 'web_darker_dark_theme_live_chat',
  1112. 'live_chat_channel_activity',
  1113. 'live_chat_emoji_picker_restyle_remain_open_on_click_to_input_area',
  1114. 'live_chat_top_chat_sampling_enabled',
  1115.  
  1116. 'live_chat_enable_mod_view',
  1117. 'live_chat_web_enable_command_handler_action_handling',
  1118. 'web_modern_dialogs',
  1119. 'web_modern_dialog_layout',
  1120. 'web_modern_typography',
  1121.  
  1122. 'kevlar_disable_component_resizing_support',
  1123. 'web_rounded_thumbnails',
  1124. 'enable_quiz_desktop_animation',
  1125. 'kevlar_thumbnail_fluid',
  1126. 'web_enable_playlist_video_lockup_equalizer',
  1127. 'web_modern_collections_v2',
  1128. 'animated_live_badge_icon',
  1129. 'use_color_palettes_modern_collections_v2',
  1130. 'web_amsterdam_post_mvp_playlists',
  1131. 'enable_desktop_search_bigger_thumbs',
  1132. 'web_animated_actions',
  1133. 'mweb_animated_actions',
  1134. 'enable_desktop_amsterdam_info_panels',
  1135.  
  1136. 'kevlar_modern_sd',
  1137. 'problem_walkthrough_sd',
  1138. 'polymer_video_renderer_defer_menu',
  1139.  
  1140.  
  1141. 'enable_html5_teal_ad_badge',
  1142. 'kevlar_ytb_live_badges',
  1143. 'live_chat_enable_new_moderator_badge',
  1144. 'live_chat_prepend_badges',
  1145. 'live_chat_bold_color_usernames',
  1146. 'render_custom_emojis_as_small_images',
  1147.  
  1148. 'web_enable_dynamic_metadata',
  1149.  
  1150. 'web_animated_like',
  1151. 'web_animated_like_lazy_load',
  1152. 'desktop_delay_player_resizing',
  1153.  
  1154.  
  1155. ...(ALLOW_THEATER_PLAYER_SHORTCUT_KEY_T ? [
  1156.  
  1157. // 'clean_up_manual_attribution_header',
  1158. // 'empty_attributed_string_killswitch',
  1159. // 'enable_profile_cards_cairo_updates',
  1160. // 'enable_teaser_framework_web_client',
  1161. // 'enable_tectonic_ad_ux_for_halftime',
  1162. // 'enable_web_shorts_save_audio_pivot',
  1163. // 'kevlar_clear_duplicate_pref_cookie',
  1164. // 'kevlar_disable_background_prefetch',
  1165. // 'kevlar_transcript_engagement_panel',
  1166. 'kevlar_watch_flexy_theater_manager',
  1167. // 'mdx_load_cast_api_bootstrap_script',
  1168. // 'web_collab_playlist_thumbnail_size',
  1169. // 'web_fix_back_button_player_loading',
  1170. // 'web_fix_dynamic_metadata_diacritic',
  1171. // 'web_kevlar_enable_adaptive_signals',
  1172. // 'web_move_autoplay_video_under_chip',
  1173. // 'web_player_small_hbp_settings_menu',
  1174. // 'web_rendererstamper_event_listener',
  1175. // 'web_shorts_skip_loading_same_index',
  1176. // 'web_shorts_suggested_action_no_bvm',
  1177. // 'web_use_updated_icon_for_oac_badge',
  1178. // 'wiz_prevent_watched_double_logging',
  1179.  
  1180. ] : []),
  1181.  
  1182. ].concat(
  1183. [
  1184. ]
  1185. );
  1186.  
  1187.  
  1188. const s = new Set(BY_PASS);
  1189.  
  1190. return s;
  1191.  
  1192. };
  1193. let cachedSet = null;
  1194.  
  1195. const hExperimentFlagsFn = () => {
  1196.  
  1197. if (brc > 4) brc = 4;
  1198.  
  1199. const use_maintain_stable_list = getSettingValue(ENABLE_EXPERIMENT_FLAGS_MAINTAIN_STABLE_LIST);
  1200. const use_maintain_reuse_components = getSettingValue(ENABLE_EXPERIMENT_FLAGS_MAINTAIN_REUSE_COMPONENTS);
  1201. const use_defer_detach = getSettingValue(ENABLE_EXPERIMENT_FLAGS_DEFER_DETACH);
  1202. const no_autoplay_toggle = getSettingValue(ENABLE_EXPERIMENT_FLAGS_NO_AUTOPLAY_TOGGLE);
  1203. ENABLE_EXPERIMENT_FLAGS_NO_AUTOPLAY_TOGGLE.currentValue = no_autoplay_toggle;
  1204.  
  1205. if (use_maintain_stable_list) Promise.resolve().then(() => console.debug("use_maintain_stable_list"));
  1206. if (use_maintain_reuse_components) Promise.resolve().then(() => console.debug("use_maintain_reuse_components"));
  1207. if (use_defer_detach) Promise.resolve().then(() => console.debug("use_defer_detach"));
  1208. if (no_autoplay_toggle) Promise.resolve().then(() => console.debug("no_autoplay_toggle"));
  1209.  
  1210. cachedSet = cachedSet || cachedSetFn({ use_maintain_stable_list, use_maintain_reuse_components, use_defer_detach, no_autoplay_toggle });
  1211.  
  1212. const mps = [];
  1213.  
  1214. setTimeout(async () => {
  1215.  
  1216. if (!mps.length) return;
  1217. let ezz = new Set();
  1218. let e1 = 999;
  1219. let e2 = -999;
  1220. for (const mp of mps) {
  1221. for (const k of mp) {
  1222. ezz.add(k);
  1223. const kl = k.length;
  1224. if (kl < e1) e1 = kl;
  1225. if (kl > e2) e2 = kl;
  1226. }
  1227. }
  1228. mps.length = 0;
  1229.  
  1230. if (!ezz.size) return;
  1231.  
  1232. await new Promise(r => window.setTimeout(r, 1));
  1233. let qt = Date.now();
  1234.  
  1235. console.log('EXPERIMENT_FLAGS', [e1, e2, ezz.size]);
  1236.  
  1237. let mf = false;
  1238. const obj = JSON.parse(localStorage['bpghn02'] || '{}');
  1239. for (const e of ezz) {
  1240. if (obj[e]) continue;
  1241. obj[e] = qt;
  1242. mf = true;
  1243. }
  1244. if (mf) {
  1245.  
  1246. localStorage['bpghn02'] = JSON.stringify(obj);
  1247. }
  1248.  
  1249. // await new Promise(r => window.setTimeout(r, 1));
  1250.  
  1251. const getEFT = function (after, offset) {
  1252.  
  1253.  
  1254. after = typeof after === 'string' ? new Date(after) : after;
  1255. let afterValue = +after;
  1256.  
  1257.  
  1258. let arr = Object.entries(obj).map(e => {
  1259. return { key: e[0], date: e[1], len: e[0].length };
  1260. }).sort((a, b) => {
  1261. return a.date < b.date ? 1 : a.date > b.date ? -1 : a.len < b.len ? 1 : a.len > b.len ? -1 : `${a.key}`.localeCompare(`${b.key}`);
  1262. });
  1263.  
  1264. if (afterValue > 0) {
  1265. arr = arr.filter(e => {
  1266. return e.date >= afterValue + offset;
  1267. })
  1268. }
  1269.  
  1270. return [arr, after, afterValue];
  1271.  
  1272. }
  1273.  
  1274. window.log_EXPERIMENT_FLAGS_Tamer = function (after, toString) {
  1275.  
  1276. let [arr, after_, afterValue] = getEFT(after, -86400000);
  1277.  
  1278. const r = {
  1279. "!log": arr,
  1280. after: afterValue > 0 ? new Date(afterValue) : null
  1281. };
  1282. console.log("log_EXPERIMENT_FLAGS_Tamer", toString ? JSON.stringify(r) : r);
  1283.  
  1284. }
  1285.  
  1286. window.kl_EXPERIMENT_FLAGS_Tamer = function (after, kl) {
  1287.  
  1288.  
  1289. let [arr, after_, afterValue] = getEFT(after, -86400000);
  1290.  
  1291. arr = arr.filter(e => {
  1292. return e.len === kl
  1293. });
  1294.  
  1295. return arr.map(e => e.key).join('|')
  1296.  
  1297.  
  1298. }
  1299.  
  1300.  
  1301. }, 800);
  1302.  
  1303. // I don't know why it requires to be extracted function.
  1304. const mex = (EXPERIMENT_FLAGS, mzFlagDetected, fEntries) => {
  1305.  
  1306. let ezz = new Set();
  1307.  
  1308. for (const [key, value] of fEntries) {
  1309.  
  1310.  
  1311. if (value === true) {
  1312.  
  1313. // if(key.indexOf('modern')>=0 || key.indexOf('enable')>=0 || key.indexOf('theme')>=0 || key.indexOf('skip')>=0 || key.indexOf('ui')>=0 || key.indexOf('observer')>=0 || key.indexOf('polymer')>=0 )continue;
  1314.  
  1315. if (mzFlagDetected.has(key)) continue;
  1316. mzFlagDetected.add(key);
  1317.  
  1318. if (cachedSet.has(key)) continue; // const BY_PASS = [
  1319.  
  1320. if (SPACEBAR_CONTROL < 0 && key.includes('speedmaster')) continue;
  1321.  
  1322. if (FLAG_STRATEGY_20240413 && key.includes('network')) continue;
  1323. if (FLAG_STRATEGY_20240413 && key.includes('less')) continue;
  1324. if (FLAG_STRATEGY_20240413 && key.includes('latency')) continue;
  1325. if (FLAG_STRATEGY_20240413 && key.includes('slow')) continue;
  1326. if (FLAG_STRATEGY_20240413 && key.includes('steam')) continue;
  1327.  
  1328. // const kl = key.length;
  1329. // const kl7 = kl % 7;
  1330. // const kl5 = kl % 5;
  1331. // const kl3 = kl % 3;
  1332. // const kl2 = kl % 2;
  1333.  
  1334. if (USE_byPassConditionAnalyzer && byPassConditionAnalyzer.testFn_(key, false)) continue;
  1335.  
  1336.  
  1337. if (key.startsWith('html5_')) {
  1338.  
  1339. if (IGNORE_VIDEO_SOURCE_RELATED) {
  1340. continue;
  1341. }
  1342.  
  1343. // if(IGNORE_VIDEO_SOURCE_RELATED){
  1344. // if(key ==='html5_enable_vp9_fairplay') continue;
  1345. // if(key ==='html5_disable_av1_hdr') continue;
  1346. // if(key ==='html5_disable_hfr_when_vp9_encrypted_2k4k_unsupported') continue;
  1347. // if(key ==='html5_account_onesie_format_selection_during_format_filter') continue;
  1348. // if(key ==='html5_prefer_hbr_vp9_over_av1') continue;
  1349. // }
  1350.  
  1351. } else if (key.startsWith('kevlar_')) {
  1352.  
  1353. } else {
  1354.  
  1355. }
  1356.  
  1357. ezz.add(key);
  1358.  
  1359. // console.log(key)
  1360. EXPERIMENT_FLAGS[key] = false;
  1361. }
  1362. }
  1363.  
  1364. mps.push(ezz);
  1365. ezz = null;
  1366. }
  1367.  
  1368. const mey = (EXPERIMENT_FLAGS, mzFlagDetected) => {
  1369. // return;
  1370.  
  1371. if (FLAG_STRATEGY_20240503) {
  1372. EXPERIMENT_FLAGS.disable_enf_isd = true;
  1373. EXPERIMENT_FLAGS.ab_det_el_h = false;
  1374. EXPERIMENT_FLAGS.ks_det_gpbl = true;
  1375. EXPERIMENT_FLAGS.ks_get_o_pp = true;
  1376. EXPERIMENT_FLAGS.ab_deg_unex_thr = true;
  1377. EXPERIMENT_FLAGS.ab_det_sc_inj_enf = false;
  1378. EXPERIMENT_FLAGS.debug_sk_em_precheck = false;
  1379. }
  1380.  
  1381. if (NO_DEBUG_FLAG) {
  1382. EXPERIMENT_FLAGS.debug_forward_web_query_parameters = false;
  1383. EXPERIMENT_FLAGS.debug_handle_relative_url_for_query_forward_killswitch = false;
  1384. EXPERIMENT_FLAGS.debug_web_ve_data = false;
  1385. }
  1386.  
  1387.  
  1388. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  1389. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_node_methods = false;
  1390. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_query_methods = false;
  1391. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  1392. EXPERIMENT_FLAGS.enable_shadydom_free_parent_node = false;
  1393. EXPERIMENT_FLAGS.enable_shadydom_free_children = false;
  1394. EXPERIMENT_FLAGS.enable_shadydom_free_last_child = false;
  1395. }
  1396.  
  1397. if (SPACEBAR_CONTROL === 0) {
  1398. EXPERIMENT_FLAGS.disable_space_scroll_fix = false;
  1399. EXPERIMENT_FLAGS.global_spacebar_pause = false;
  1400. EXPERIMENT_FLAGS.web_speedmaster_spacebar_control = false;
  1401. } else if (SPACEBAR_CONTROL === 1) {
  1402.  
  1403. EXPERIMENT_FLAGS.disable_space_scroll_fix = false;
  1404. EXPERIMENT_FLAGS.global_spacebar_pause = true;
  1405. EXPERIMENT_FLAGS.web_speedmaster_spacebar_control = false;
  1406. } else if (SPACEBAR_CONTROL === 2) {
  1407.  
  1408. EXPERIMENT_FLAGS.disable_space_scroll_fix = false;
  1409. EXPERIMENT_FLAGS.global_spacebar_pause = true;
  1410. EXPERIMENT_FLAGS.web_speedmaster_spacebar_control = true;
  1411. }
  1412.  
  1413. EXPERIMENT_FLAGS.use_cfr_monitor = false;
  1414. EXPERIMENT_FLAGS.skip_network_check_if_cfr = false;
  1415.  
  1416. if (FLAG_STRATEGY_20240413) {
  1417. EXPERIMENT_FLAGS.kevlar_watch_grid = false;
  1418. EXPERIMENT_FLAGS.kevlar_watch_grid_hide_chips = false;
  1419. EXPERIMENT_FLAGS.kevlar_watch_grid_reduced_top_margin_rich_grid = false;
  1420. EXPERIMENT_FLAGS.kevlar_watch_grid_top_companion = false;
  1421. EXPERIMENT_FLAGS.kevlar_watch_fixie = false;
  1422. EXPERIMENT_FLAGS.kevlar_watch_grid_auto_open_playlist = false;
  1423. EXPERIMENT_FLAGS.action_companion_center_align_description = false;
  1424. EXPERIMENT_FLAGS.action_companion_truncate_domain = false;
  1425. }
  1426.  
  1427. if (ENABLE_MINOR_CHAT_FEATURE_UPGRADE) {
  1428.  
  1429.  
  1430. EXPERIMENT_FLAGS.web_supports_animations_api = true;
  1431. EXPERIMENT_FLAGS.smartimation_background = true;
  1432. // EXPERIMENT_FLAGS.register_web_smartimations_component = true;
  1433.  
  1434. EXPERIMENT_FLAGS.enable_native_live_chat_on_kevlar = true;
  1435.  
  1436. EXPERIMENT_FLAGS.live_chat_enable_qna_replay = true;
  1437. EXPERIMENT_FLAGS.live_chat_aggregation = true;
  1438. EXPERIMENT_FLAGS.live_chat_web_use_emoji_manager_singleton = true;
  1439. // EXPERIMENT_FLAGS.enable_docked_chat_messages = true;
  1440.  
  1441. EXPERIMENT_FLAGS.live_chat_mention_regex_update = true;
  1442.  
  1443. }
  1444.  
  1445. // EXPERIMENT_FLAGS.live_chat_taller_emoji_picker = true;
  1446. // EXPERIMENT_FLAGS.live_chat_web_input_update = true;
  1447.  
  1448. if (ENABLE_EMOJI_PICKER_NEW_STYLE) {
  1449.  
  1450. EXPERIMENT_FLAGS.live_chat_emoji_picker_restyle = true;
  1451. EXPERIMENT_FLAGS.live_chat_emoji_picker_restyle_remain_open_on_send = true;
  1452. EXPERIMENT_FLAGS.live_chat_taller_emoji_picker = false;
  1453.  
  1454. }
  1455.  
  1456. if (ENABLE_BADGE_STYLE) {
  1457.  
  1458. EXPERIMENT_FLAGS.enable_html5_teal_ad_badge = true;
  1459. EXPERIMENT_FLAGS.kevlar_ytb_live_badges = true;
  1460. EXPERIMENT_FLAGS.live_chat_enable_new_moderator_badge = true;
  1461. EXPERIMENT_FLAGS.live_chat_prepend_badges = true;
  1462.  
  1463. EXPERIMENT_FLAGS.live_chat_bold_color_usernames = true;
  1464. EXPERIMENT_FLAGS.render_custom_emojis_as_small_images = true;
  1465.  
  1466.  
  1467. }
  1468.  
  1469. // EXPERIMENT_FLAGS.kevlar_wiz_prototype_enable_all_components = true;
  1470.  
  1471.  
  1472. EXPERIMENT_FLAGS.html5_allow_asmjs = true;
  1473. EXPERIMENT_FLAGS.html5_honor_caption_availabilities_in_audio_track = true;
  1474. EXPERIMENT_FLAGS.web_player_hide_nitrate_promo_tooltip = true;
  1475. EXPERIMENT_FLAGS.html5_enable_vod_slar_with_notify_pacf = true;
  1476. EXPERIMENT_FLAGS.html5_recognize_predict_start_cue_point = true;
  1477. EXPERIMENT_FLAGS.enable_player_logging_lr_home_infeed_ads = false;
  1478.  
  1479. EXPERIMENT_FLAGS.log_gel_compression_latency = true;
  1480. EXPERIMENT_FLAGS.log_gel_compression_latency_lr = true;
  1481. EXPERIMENT_FLAGS.log_jspb_serialize_latency = true;
  1482.  
  1483. if (NO_REFRESH) {
  1484.  
  1485. EXPERIMENT_FLAGS.kevlar_watch_metadata_refresh_standardized_body_typography = false;
  1486. EXPERIMENT_FLAGS.kevlar_refresh_gesture = false;
  1487.  
  1488. }
  1489.  
  1490.  
  1491. if (NO_DESKTOP_DELAY_PLAYER_RESIZING) {
  1492.  
  1493. EXPERIMENT_FLAGS.desktop_delay_player_resizing = false;
  1494. }
  1495. if (NO_ANIMATED_LIKE) {
  1496. EXPERIMENT_FLAGS.web_animated_like = false;
  1497. EXPERIMENT_FLAGS.web_animated_like_lazy_load = false;
  1498. }
  1499.  
  1500. if (use_maintain_stable_list) {
  1501. if (USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true : true) {
  1502. // EXPERIMENT_FLAGS.kevlar_tuner_should_test_maintain_stable_list = true; // timestamp toggle issue
  1503. EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list = true;
  1504. // EXPERIMENT_FLAGS.kevlar_tuner_should_maintain_stable_list = true; // fallback // timestamp toggle issue
  1505. }
  1506. }
  1507.  
  1508. if (use_maintain_reuse_components) {
  1509. EXPERIMENT_FLAGS.kevlar_tuner_should_test_reuse_components = true;
  1510. EXPERIMENT_FLAGS.kevlar_tuner_should_reuse_components = true;
  1511. EXPERIMENT_FLAGS.kevlar_should_reuse_components = true; // fallback
  1512. }
  1513.  
  1514. if (use_defer_detach) {
  1515. EXPERIMENT_FLAGS.kevlar_tuner_should_defer_detach = true;
  1516. }
  1517.  
  1518. // EXPERIMENT_FLAGS.kevlar_prefetch_data_augments_network_data = true; // TBC
  1519.  
  1520. EXPERIMENT_FLAGS.kevlar_clear_non_displayable_url_params = true;
  1521. EXPERIMENT_FLAGS.kevlar_clear_duplicate_pref_cookie = true;
  1522. // EXPERIMENT_FLAGS.kevlar_unified_player_clear_watch_next_killswitch = true;
  1523. EXPERIMENT_FLAGS.kevlar_player_playlist_use_local_index = true;
  1524. // EXPERIMENT_FLAGS.kevlar_non_watch_unified_player = true;
  1525. // EXPERIMENT_FLAGS.kevlar_player_update_killswitch = true;
  1526.  
  1527. EXPERIMENT_FLAGS.web_secure_pref_cookie_killswitch = true;
  1528. EXPERIMENT_FLAGS.ytidb_clear_optimizations_killswitch = true;
  1529. // EXPERIMENT_FLAGS.defer_overlays = true;
  1530.  
  1531.  
  1532. if (COMMENTS_NO_DELAY) {
  1533. EXPERIMENT_FLAGS.kevlar_tuner_default_comments_delay = 0;
  1534. EXPERIMENT_FLAGS.kevlar_tuner_run_default_comments_delay = false;
  1535. }
  1536.  
  1537. }
  1538. const setterFn = (EXPERIMENT_FLAGS, mzFlagDetected) => {
  1539.  
  1540. const fEntries = Object.entries(EXPERIMENT_FLAGS);
  1541. mex(EXPERIMENT_FLAGS, mzFlagDetected, fEntries);
  1542. mey(EXPERIMENT_FLAGS, mzFlagDetected);
  1543.  
  1544. };
  1545.  
  1546. return setterFn;
  1547.  
  1548.  
  1549. };
  1550.  
  1551. let _setterFn = null;
  1552.  
  1553. const setupConfig = (config_) => {
  1554.  
  1555. if (config_.EXPERIMENT_FLAGS) {
  1556.  
  1557. const setterFn = _setterFn || (_setterFn = hExperimentFlagsFn());
  1558.  
  1559. setterFn(config_.EXPERIMENT_FLAGS, mzFlagDetected1);
  1560.  
  1561. if (config_.EXPERIMENTS_FORCED_FLAGS) setterFn(config_.EXPERIMENTS_FORCED_FLAGS, mzFlagDetected2);
  1562. }
  1563.  
  1564. const playerKevlar = (config_.WEB_PLAYER_CONTEXT_CONFIGS || 0).WEB_PLAYER_CONTEXT_CONFIG_ID_KEVLAR_WATCH || 0;
  1565.  
  1566. if (playerKevlar && !zPlayerKevlar) {
  1567. zPlayerKevlar = true;
  1568.  
  1569. if (NO_SerializedExperiment && typeof playerKevlar.serializedExperimentFlags === 'string' && typeof playerKevlar.serializedExperimentIds === 'string') {
  1570. fixSerializedExperiment(playerKevlar);
  1571. }
  1572.  
  1573. }
  1574.  
  1575. }
  1576.  
  1577.  
  1578. const looperFn = (config_) => {
  1579. if (--brc < 0) return;
  1580.  
  1581. if (!config_) {
  1582. try {
  1583. config_ = yt.config_ || ytcfg.data_;
  1584. } catch (e) { }
  1585. }
  1586. if (config_) setupConfig(config_);
  1587.  
  1588. };
  1589.  
  1590.  
  1591. window._ytConfigHacks.add((config_) => {
  1592. looperFn(config_);
  1593. });
  1594. looperFn();
  1595.  
  1596. if (isMainWindow) {
  1597.  
  1598. console.groupCollapsed(
  1599. "%cYouTube EXPERIMENT_FLAGS Tamer",
  1600. "background-color: #EDE43B ; color: #000 ; font-weight: bold ; padding: 4px ;"
  1601. );
  1602.  
  1603. console.log("Script is loaded.");
  1604. console.log("This might affect the new features when YouTube rolls them out to general users.");
  1605. console.log("If you found any issue in using YouTube, please disable this script to check whether the issue is due to this script or not.");
  1606.  
  1607. console.groupEnd();
  1608.  
  1609. }
  1610.  
  1611. })();