{ "metadata": { "name": "", "signature": "sha256:b3db3d09e064cfe84d747d44f9507670e8eab728c8bb5cbb4ed2b6cb99f11a98" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "code", "collapsed": false, "input": [ "import json, re, subprocess, urllib2\n", "\n", "def get_fps_given_nframes(url, nframes):\n", " try:\n", " out = subprocess.check_output(['ffprobe', '-i', url, '-show_frames', '-read_intervals', '%+#' + str(nframes), '-select_streams', 'v'], stderr=subprocess.STDOUT)\n", " except subprocess.CalledProcessError:\n", " return None\n", " frametimes = [float(match.group(1)) for match in re.finditer(r'pts_time=([\\d\\.]+)', out)]\n", " # frametimes contain the beginning timestamps of each frame\n", " # len(frametimes) - 1 is the numerator below due to fencepost:\n", " fps = (len(frametimes) - 1) / (max(frametimes) - min(frametimes)) \n", " return fps\n", "\n", "def print_fps_stats(root_url):\n", " r = json.loads(urllib2.urlopen(root_url + '/r.json').read())\n", " nframes = int(r['frames']) + int(r['leader'])\n", " advertised_fps = float(r['fps'])\n", " print '%s:' % root_url\n", " for video in ['/0/0/0.mp4', '/0/0/0.webm']:\n", " url = root_url + video\n", " actual_fps = get_fps_given_nframes(url, nframes)\n", " if actual_fps != None:\n", " print (' %s: %d frames, advertised %.4f, actual %.4f, adv/act = %.2f%%' % \n", " (video, nframes, advertised_fps, actual_fps, advertised_fps / actual_fps * 100.0))\n", " else:\n", " print ' %s: not found' % video" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compare actual FPS versus advertised FPS\n", "========================================" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Earth Engine\n", "------------\n", "FPS are right on the money for both mp4 and webm" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print_fps_stats('https://earthengine.google.org/timelapse/data/20130507/1068x600')\n", "print_fps_stats('http://commondatastorage.googleapis.com/earthengine-timelapse/seasonal-20140202/1068x600')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "https://earthengine.google.org/timelapse/data/20130507/1068x600:\n", " /0/0/0.mp4: 29 frames, advertised 10.0000, actual 10.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: 29 frames, advertised 10.0000, actual 10.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://commondatastorage.googleapis.com/earthengine-timelapse/seasonal-20140202/1068x600:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 634 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: 634 frames, advertised 12.0000, actual 12.0002, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 174 }, { "cell_type": "markdown", "metadata": {}, "source": [ "timemachine.cmucreatelab.org\n", "----------------------------\n", "\n", "Almost all the FPS are 100% accurate for both mp4 and webm. The one exception is Blue Marble, which is 99.98%, but since it's only 12 frames long, such a tiny error only results in a .0024 frame error by the end. (Perhaps it's a lack of precision in reading the frame time, in which case the % error would naturally go down in the longer videos).\n", "\n", "An aside: some of the appended black trailers for .mp4 appear to be have a different FPS from the main video, so print_fps_stats compensates by only looking at the frames before the trailer.\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print_fps_stats('http://g7.gigapan.org/timemachines/brassica-15m-g10-bf0-l/brassica-15m-g10-bf0-l-1088x624')\n", "print_fps_stats('http://g7.gigapan.org/timemachines/e5-crf28-g10-bf0-l/e5-crf28-g10-bf0-l90-25fps-1088x624')\n", "print_fps_stats('http://g7.gigapan.org/timemachines/blue-marble-v2/blue-marble-v2-crf28-6fps-1088x624')\n", "print_fps_stats('http://g7.gigapan.org/timemachines/pittsburgh-v12/crf26-12fps-l70-1088x624')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "http://g7.gigapan.org/timemachines/brassica-15m-g10-bf0-l/brassica-15m-g10-bf0-l-1088x624:\n", " /0/0/0.mp4: 3130 frames, advertised 25.0000, actual 25.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: 3130 frames, advertised 25.0000, actual 25.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://g7.gigapan.org/timemachines/e5-crf28-g10-bf0-l/e5-crf28-g10-bf0-l90-25fps-1088x624:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1457 frames, advertised 25.0000, actual 25.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: 1457 frames, advertised 25.0000, actual 25.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://g7.gigapan.org/timemachines/blue-marble-v2/blue-marble-v2-crf28-6fps-1088x624:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 12 frames, advertised 6.0000, actual 6.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: 12 frames, advertised 6.0000, actual 6.0011, adv/act = 99.98%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://g7.gigapan.org/timemachines/pittsburgh-v12/crf26-12fps-l70-1088x624:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 15271 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: 15271 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "BreatheCam\n", "----------\n", "\n", "Looks like the transition from spot-on to 100.08% happens on March 10, which appears to be the same day the URL pattern for\n", "the root directory changes. 100.08% * 1440 frames ~= 1489.2, so the error is definitely enough to give us errors seeking." ] }, { "cell_type": "code", "collapsed": false, "input": [ "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-02-17.timemachine/crf26-12fps-l70-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-01.timemachine/crf26-12fps-l70-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-04.timemachine/crf26-12fps-l70-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-07.timemachine/crf26-12fps-l70-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-08.timemachine/crf26-12fps-l70-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-09.timemachine/crf26-12fps-l70-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-10.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-11.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-12.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-15.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-20.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-04-01.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-05-01.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-06-01.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-07-01.timemachine/crf26-12fps-1424x800')\n", "print_fps_stats('http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-08-01.timemachine/crf26-12fps-1424x800')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-02-17.timemachine/crf26-12fps-l70-1424x800:\n", " /0/0/0.mp4: 1510 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-01.timemachine/crf26-12fps-l70-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1488 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-04.timemachine/crf26-12fps-l70-1424x800:\n", " /0/0/0.mp4: 1506 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-07.timemachine/crf26-12fps-l70-1424x800:\n", " /0/0/0.mp4: 1510 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-08.timemachine/crf26-12fps-l70-1424x800:\n", " /0/0/0.mp4: 1506 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-09.timemachine/crf26-12fps-l70-1424x800:\n", " /0/0/0.mp4: 1450 frames, advertised 12.0000, actual 12.0000, adv/act = 100.00%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-10.timemachine/crf26-12fps-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1388 frames, advertised 12.0000, actual 11.9910, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-11.timemachine/crf26-12fps-1424x800:\n", " /0/0/0.mp4: 1488 frames, advertised 12.0000, actual 11.9909, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-12.timemachine/crf26-12fps-1424x800:\n", " /0/0/0.mp4: 1494 frames, advertised 12.0000, actual 11.9910, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-15.timemachine/crf26-12fps-1424x800:\n", " /0/0/0.mp4: 1498 frames, advertised 12.0000, actual 11.9909, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-03-20.timemachine/crf26-12fps-1424x800:\n", " /0/0/0.mp4: 1508 frames, advertised 12.0000, actual 11.9909, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-04-01.timemachine/crf26-12fps-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1468 frames, advertised 12.0000, actual 11.9909, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-05-01.timemachine/crf26-12fps-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1508 frames, advertised 12.0000, actual 11.9909, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-06-01.timemachine/crf26-12fps-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1508 frames, advertised 12.0000, actual 11.9909, adv/act = 100.08%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-07-01.timemachine/crf26-12fps-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 875 frames, advertised 12.0000, actual 11.9913, adv/act = 100.07%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "http://timemachine1.gc.cs.cmu.edu/timemachines/breathecam/timemachines/heinz/2014-08-01.timemachine/crf26-12fps-1424x800:" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.mp4: 1078 frames, advertised 12.0000, actual 11.9911, adv/act = 100.07%" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", " /0/0/0.webm: not found" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Code that's no longer needed:\n", "-----------------------------" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def get_fps_nframes(url):\n", " try:\n", " out = subprocess.check_output(['ffprobe', '-i', url, '-show_frames', '-select_streams', 'v'], stderr=subprocess.STDOUT)\n", " except subprocess.CalledProcessError:\n", " return (None, None)\n", " nframes = len(list(re.finditer(r'\\[FRAME\\]', out)))\n", " components = re.search(r'Duration: ([\\:\\.\\d]+)', out).group(1).split(':')\n", " if len(components) != 3:\n", " raise(\"Unrecognized format for duration\")\n", " duration = 3600 * float(components[0]) + 60 * float(components[1]) + float(components[2])\n", " print 'duration=%g' % duration\n", " return (nframes / duration, nframes)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 } ], "metadata": {} } ] }