PageSourceSearch

https://www.seattlemcm.com/views/templates/_common/js/youtube-cc-off.js?v=100542

js seattlemcm.com collected 2026-10-08 05:41:17 UTC 3,050 bytes, 65 lines download raw bytes

1// Turn off YouTube auto-captions on embedded players.
2// YouTube has no player parameter to force captions OFF (cc_load_policy=1 can only force
3// them ON), and embeds frequently auto-enable captions/auto-generated lyrics even when the
4// same video shows none on youtube.com. This wraps each embed with the IFrame API and
5// clears the active caption track when YouTube applies one. The CC button stays available,
6// so viewers who want captions can still turn them on manually.
7// YouTube applies the auto-caption track around the start of playback, so a single clear
8// on ready is not enough: we retry for a short window after the first play, then stand
9// down permanently so a viewer's manual CC choice is never overridden.
10// Only targets iframes whose src includes enablejsapi=1 (set in the video/header card templates).
11(function () {
12    var frames = document.querySelectorAll('iframe[src*="youtube.com/embed/"], iframe[src*="youtube-nocookie.com/embed/"]');
13    var targets = [];
14    for (var i = 0; i < frames.length; i++) {
15        if (frames[i].src.indexOf("enablejsapi=1") !== -1) targets.push(frames[i]);
16    }
17    if (!targets.length) return;
18
19    function clearCaptions(player) {
20        var opts = (player.getOptions && player.getOptions()) || [];
21        if (opts.indexOf("captions") !== -1) player.setOption("captions", "track", {});
22        if (opts.indexOf("cc") !== -1) player.setOption("cc", "track", {});
23    }
24
25    function wrap(el) {
26        var done = false;      // stop interfering after the post-play clear window
27        var played = false;
28        new YT.Player(el, {
29            events: {
30                onReady: function (e) { clearCaptions(e.target); },
31                // Captions module usually loads just before/at playback start.
32                onApiChange: function (e) { if (!done) clearCaptions(e.target); },
33                onStateChange: function (e) {
34                    if (e.data === YT.PlayerState.PLAYING && !played) {
35                        played = true;
36                        var p = e.target;
37                        clearCaptions(p);
38                        setTimeout(function () { clearCaptions(p); }, 250);
39                        setTimeout(function () { clearCaptions(p); }, 750);
40                        setTimeout(function () { clearCaptions(p); done = true; }, 1500);
41                    }
42                }
43            }
44        });
45    }
46
47    function initPlayers() {
48        for (var i = 0; i < targets.length; i++) wrap(targets[i]);
49    }
50
51    if (window.YT && window.YT.Player) {
52        initPlayers();
53    } else {
54        var prev = window.onYouTubeIframeAPIReady;
55        window.onYouTubeIframeAPIReady = function () {
56            if (typeof prev === "function") prev();
57            initPlayers();
58        };
59        if (!document.querySelector('script[src*="youtube.com/iframe_api"]')) {
60            var tag = document.createElement("script");
61            tag.src = "https://www.youtube.com/iframe_api";
62            document.head.appendChild(tag);
63        }
64    }
65})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.