9

How can it be determined if a youtube video is an actual video or just a static image?

Since it's likely not possible using the youtube API, is there a workaround using javascript/jquery to scan pixels in a given area of the window and determine if they've changed?

d-_-b
  • 21,536
  • 40
  • 150
  • 256
mrabin
  • 662
  • 10
  • 19

4 Answers4

11

This rough idea is based on the answer of Stichoza, but much simpler.

Use just thumbnails

You can get video thumbnails http://i.ytimg.com/vi/VIDEO_ID/X.jpg. For example, if Video ID is 500Pm4mQZQQ (static image video), you will have this thumbnails:

http://i.ytimg.com/vi/500Pm4mQZQQ/1.jpg
http://i.ytimg.com/vi/500Pm4mQZQQ/2.jpg
http://i.ytimg.com/vi/500Pm4mQZQQ/3.jpg

If these images are very similar, the video is static (they won't be exactly identical because of compression noise). In order to compare the three available still images in a simple way, you don't need to apply actual image comparison algorithms. Just compare their file sizes.

The idea: compare JPEG sizes

These are JPEG images. Their file size varies, depending on how well the image can be compressed. Similar images will result in similar file sizes.

The above examples have 3534, 3539, and 3539 bytes. Checking some random non-static video, I get much bigger differences: 4179, 4726, and 4779 bytes. Very similar file sizes = static video.

Get started

Getting the byte size of an image is not (easily) possible with Javascript. But it should be trivial with any server-side technique. Here's an easy way with PHP:

$head = array_change_key_case(get_headers("http://example.com/file.ext", TRUE));
$filesize = $head['content-length'];

Edit:

Test implementation in PHP:

<?php
$urls = array(
    // Actual videos
    'https://www.youtube.com/watch?v=1iTg20x7w2s',
    'https://www.youtube.com/watch?v=uY6ooLaM3_U',
    'https://www.youtube.com/watch?v=E0vNU6pEQLU',
    // Static videos
    'https://www.youtube.com/watch?v=wWiC_I7R2iI',
    'https://www.youtube.com/watch?v=ytbpMht-7OA',
    'https://www.youtube.com/watch?v=x_38wF6bYCw'
);

foreach($urls as $url) {
    echo $url . ":\n";
    echo thumbSizeStandardDeviation($url) . "\n\n";
}

/**
 * This is the main function
 */
function thumbSizeStandardDeviation($url) {
    $videoId = extractVideoId($url);

    for($i = 1; $i <= 3; $i++) {
        $thumbnailUrl =
            "http://i.ytimg.com/vi/" . $videoId . "/" . $i . ".jpg";
        $fileSizes[] = getRemoteFileSize($thumbnailUrl);
    }

    return standardDeviation($fileSizes);
}

/**
 * https://stackoverflow.com/a/3393008/376138
 */
function extractVideoId($url) {
    parse_str( parse_url( $url, PHP_URL_QUERY ), $queryParams );
    return $queryParams['v'];
}

/**
 * https://stackoverflow.com/a/12249536/376138
 */
function getRemoteFileSize($url) {
    $headers = array_change_key_case(get_headers($url, TRUE));
    return $headers['content-length'];
}

/**
 * https://en.wikipedia.org/wiki/Standard_deviation#Basic_examples
 */
function standardDeviation($numbers) {
    $mean = array_sum($numbers) / count($numbers);
    $differenceSum = 0;
    foreach($numbers as $number) {
        $differenceSum += pow($number - $mean, 2);
    }
    return sqrt($differenceSum / count($numbers));
}

Test result:

I've used three "normal" videos and three completely static videos, their URLs are in the code. Running the script at the command line, I get:

$ php youtube-is-static-video.php
https://www.youtube.com/watch?v=1iTg20x7w2s:
271.21496189472

https://www.youtube.com/watch?v=uY6ooLaM3_U:
28.335294049805

https://www.youtube.com/watch?v=E0vNU6pEQLU:
182.70620010157

https://www.youtube.com/watch?v=wWiC_I7R2iI:
4.1899350299922

https://www.youtube.com/watch?v=ytbpMht-7OA:
7.5424723326565

https://www.youtube.com/watch?v=x_38wF6bYCw:
5.1854497287013

In this (admittedly small) sample it is indeed possible to tell the normal (first three) from the static ones (last three).

A big problem will be videos made of multiple still images (slideshow), which is quite common for music uploads.

Community
  • 1
  • 1
pixelistik
  • 7,541
  • 3
  • 32
  • 42
5

There is no official way to determine if video is static image on not, but you can still do some tricks.

You can get video thumbnails http://i.ytimg.com/vi/VIDEO_ID/X.jpg. For example, if Video ID is 500Pm4mQZQQ (static image video), you will have this thumbnails:

Now you can use Image Similarity Detection libraries to determine thumbnails' similarity. For example, you can use this js-image-similarity JavaScript algorithm: https://github.com/bitlyfied/js-image-similarity

Note: This JS library is only supposed to work in latest WebKit. Supports for Canvas and Array.forEach is required.

You can also use PHP. Read more about algorithm here and also check this PHP Class: http://www.phpclasses.org/package/6478-PHP-Compare-two-images-to-find-the-differences.html

Stichoza
  • 4,491
  • 2
  • 23
  • 24
  • +1. I was about to say the same thing but you beat me to it. There is a [question on SO about getting video thumbnails](http://stackoverflow.com/q/2068344/87015) – Salman A Feb 13 '13 at 19:00
2

No, sorry. There is no support in the YouTube APIs for retrieving information about either the audio or visual content that's being played.

Jeff Posnick
  • 53,580
  • 14
  • 141
  • 167
1

This is not supported by YouTube API, but it should be possible for HTML5 videos. Using HTML5 You can copy a single frame as if it was an image. Next it's possible to manipulate single pixels.

Following code gets pixels data from a single frame (video):

bcv.drawImage(video, 0, 0, w, h); /* bcv is a canvas object */
var apx = bcv.getImageData(0, 0, w, h);
var data = apx.data;
Mike
  • 1,158
  • 5
  • 22
  • 32
  • Of course this would only work for HTML5 videos, which is not a standard so far. – Mike Feb 13 '13 at 14:39
  • Thanks, i'll check this out! Not sure if this'll work because of the html5 but definitely good to know! – d-_-b Feb 13 '13 at 15:33