dan-lee
dan-lee

Reputation: 14502

Change source of embedded flash object in YouTube

I'd like to change the source swf file of a YouTube video. The video is an <embed> element.

How it's built:

<embed width="640" id="movie_player-flash" height="390"
       tabindex="0" type="application/x-shockwave-flash"
       src="http://s.ytimg.com/yt/swfbin/watch_as3-vfl07wZSq.swf" flasvars="...">

(An example may be found on Google's YouTube channel)

I left out some attributes and the content of flashvars as it is a long string with settings, does this affect the video at all?


What I've tried:

  1. I tried by simply changing the src attribute, but that doesn't affect anything:

    document.getElementById('movie_player-flash').src = url;
    
  2. I also tried to clone the original, change the source and re-append it. And again: nothing:

    var player = document.getElementById('movie_player-flash');
    var playerClone = player.cloneNode(true);
    playerClone.setAttribute('src', url);
    
    player.parentNode.replaceChild(playerClone, player);
    

Does anybody know how to accomplish changing the video source?

Upvotes: 1

Views: 2368

Answers (1)

Brock Adams
Brock Adams

Reputation: 93533

There are many issues here:

  1. The flash video is not always in <embed id="movie_player-flash", sometimes it is in <embed id="movie_player". Since this is Google, there are probably other schemes as well. So, a simple document.getElementById('movie_player-flash') is right out. Use something like:

    var flashEmbed  = document.querySelectorAll ("#movie_player-flash, #movie_player");
    if (flashEmbed.length) {
        flashEmbed  = flashEmbed[0];
        // DO THE SWITCH HERE.
    }
    


  2. Just changing the src attribute does work, but only in rare circumstances. If you are switching to a different video that:

    1. Requires no parameters. (Although you might be able to restore these by creating the appropriate <object> and <param> tags.)
    2. Loads no external dependencies. These will be blocked by cross-domain security, if they are not on the same domain as the target page. Additionally, the paths of objects a flash file loads are often fixed within the file itself (Possibly giving 404 errors, even if same domain).

    Then, it can work. See this Fiddle.

  3. Re:

    I left out some attributes and the content of flashvars as it is a long string with settings, does this affect the video at all?

    On modern Youtube, the flashvars are everything! Also, if you compare the src attribute, you'll see that it is the same for most all flash videos. For example, no matter what video I try, currently the src is http://s.ytimg.com/yt/swfbin/watch_as3-vfl07wZSq.swf.

    That's because the flash object, loaded by the the <embed> tag, is not the video. It is a shell object that loads the player (and other things), and the player loads the actual video file.

    So, nominally, to change one Youtube video into another, you must change the parameters and/or flashvars. Even if you change the src to an old-style, direct <embed> link (EG: http://www.youtube.com/v/uY3LAFJbKyY?version=3&amp;hl=en_US&amp;rel=0), it will only appear to work until the Play button is pressed. Then the video as defined in the parameters will return and play.

  4. However, Youtube still preserves aspects of the old system (for now). So, if you can find the old-style embedding link, you can swap the src to that and replace the <embed> with one that has no flashvars. See the code at the end of the answer.

    Here's one way to find the old-style embedding link:

    1. On the video's Youtube page, press the Share button.
    2. Press the Embed button.
    3. Check the Use old embed code checkbox.
    4. The textarea will now display <object>...<embed>... HTML. Copy that out and extract just the <embed> src attribute. (EG:

      http://www.youtube.com/v/uY3LAFJbKyY?version=3&amp;hl=en_US&amp;rel=0
      

      )
      Discard everything else.

  5. The flash element does not always load right away. It can also be replaced via AJAX. So, we may need to wait for the (right) <embed> to appear.
    For simplicity, I'll show this with setInterval(), but for a robust, practical solution, you'll want to use the waitForKeyElements() utility, as shown in this answer.


Putting it all together, here is a complete Greasemonkey script that swaps out most videos:

// ==UserScript==
// @name        _Youtube, replace flash video
// @description Replaces most videos with the Greatest Video Of All Time!
// @include     http://www.youtube.com/watch*
// @include     http://www.youtube.com/user*
// @grant       none
// ==/UserScript==

var embedChkIntval  = setInterval ( function () {
        var flashEmbed  = document.querySelectorAll ("#movie_player-flash, #movie_player");
        if (flashEmbed.length) {
            var playerClone = flashEmbed[0].cloneNode (true);
            playerClone.src = 'http://www.youtube.com/v/dQw4w9WgXcQ?version=3&amp;hl=en_US&amp;rel=0';
            playerClone.removeAttribute ("flashvars");

            flashEmbed[0].parentNode.replaceChild (playerClone, flashEmbed[0]);
            clearInterval (embedChkIntval);
        }
    },
    150
);

Upvotes: 2

Related Questions