Archive for October, 2008

Get the URL of a YouTube FLV in Flash

Friday, October 31st, 2008

YouTube recently changed the way it serves FLV videos and previous methods to get the URL of the FLV files no longer work. As a workaround, it is still possible to retrieve it by:

1. Downloading the YouTube webpage where the video is embedded
2. Parsing it to extract the “t” and “video_id” parameters
3. Building the FLV URL using the old method.

Obviously, having to download and parse the YouTube web page is a lot slower than the previous method, which was just about reading the HTTP headers, but at least it works.

The code snippet below allows to do just that:

public function getFLVURL(iYouTubeVideoURL) {
  // iYouTubeVideoURL is the "watch" URL such as:
  // http://www.youtube.com/watch?v=OVVvAnU3m6E

  var loader:URLLoader = new URLLoader();
  var req:URLRequest = new URLRequest(iYouTubeVideoURL);
  loader.addEventListener(Event.COMPLETE, this.getFLVURL_complete);
  loader.addEventListener(IOErrorEvent.IO_ERROR, this.getFLVURL_ioError);
  loader.load(req);
}

private function getFLVURL_complete(iEvent) {
  var pageData:String = iEvent.currentTarget.data;

  // Get the "t" parameter
  var regex:RegExp = /"t": "(.*?)"/;
  var result:Array = pageData.match(regex);
  if (result.length < 2) {
    trace("Error parsing YouTube page: Couldn't get 't' parameter");
    return;
  }
  var param_t = result[1];

  // Get the "video_id" parameter
  regex = /"video_id": "(.*?)"/;
  result = pageData.match(regex);
  if (result.length < 2) {
    trace("Error parsing YouTube page: Couldn't get 'video_id' parameter");
    return;
  }
  var param_video_id = result[1];

  var flvURL:String = constructFLVURL(param_video_id, param_t);
  trace("Here's the FLV URL: " + flvURL);

  flvTextBox.text = flvURL;
}

private function getFLVURL_ioError(iEvent) {
  var loader = iEvent.target;
  trace("Couldn't download YouTube web page: " + iEvent);
}

private function constructFLVURL (video_id:String, t:String):String {
  var str:String = "http://www.youtube.com/get_video.php?";
  str += "video_id=" + video_id;
  str += "&t=" + t;
  return str;
}

Update (01/12/2008):

As it turns out, this technique only works from Adobe AIR and not from a web page. This is because YouTube doesn’t allow crossdomain calls, which means that if a Flash application tries to fetch one of their pages, it will fail with a security error.

To go around this issue, it is possible to use a simple PHP stub file, which fetches the YouTube page and send it back to Flash. The PHP file would be as follow:

<?php

$url = urldecode($_GET["url"]);
header("Content-Type: text/html");
readfile($url);

?>

Then, in Flash, instead of calling the YouTube URL directly, you call the PHP URL:

var youTubeURL = "http://uk.youtube.com/watch?v=bxfpMGLMZ7Y"
var stubURL = "http://example.com/stub.php?url=" + escape(youTubeURL)
getFLVURL(stubURL);

This small demo illustrates all that. The source code with PHP stub is available here.

Update (19/03/2009):

I’ve posted a follow up to this post with some information on how to get the HD quality version of the videos:
Get the URL of an HD-quality Youtube video.

Create a short unique ID in PHP

Tuesday, October 21st, 2008

Mads Kristensen describes a nice way of generating shorter UUIDs in C#. The idea is to take the 16 bytes of a UUID and convert them to a readable string via a Base64 encoder. The result is a string of 22 characters instead of 32, which is particularly convenient for web services since it makes the URLs 10 characters shorter.

I’ve implemented a version of it in PHP. Just copy and paste the code below and call createBase64UUID()

function createBase64UUID() {
  $uuid com_create_guid();
  $byteString "";

  // Remove the dashes from the string
  $uuid str_replace("-"""$uuid);

  // Remove the opening and closing brackets
  $uuid substr($uuid1strlen($uuid) - 2); 

  // Read the UUID string byte by byte
  for($i 0$i strlen($uuid); $i += 2) {
    // Get two hexadecimal characters
    $s substr($uuid$i2);
    // Convert them to a byte
    $d hexdec($s);
    // Convert it to a single character
    $c chr($d);
    // Append it to the byte string
    $byteString $byteString.$c;
  } 

  // Convert the byte string to a base64 string
  $b64uuid base64_encode($byteString);
  // Replace the "/" and "+" since they are reserved characters
  $b64uuid str_replace("/""_"$b64uuid);
  $b64uuid str_replace("+""-"$b64uuid);
  // Remove the trailing "=="
  $b64uuid substr($b64uuid0strlen($b64uuid) - 2); 

  return $b64uuid;
}
Copyright © Pogopixels Ltd, 2008-2018