You are here

public function PHPVideoToolkit::parseFileInfo in Video 7.2

Parses file information returned by ffmpeg -i

Parameters

$raw: Return text of ffmpeg -i

Return value

Array containing various data about the file

1 call to PHPVideoToolkit::parseFileInfo()
PHPVideoToolkit::getFileInfo in libraries/phpvideotoolkit/phpvideotoolkit.php5.php
Returns information about the specified file without having to use ffmpeg-php as it consults the ffmpeg binary directly. This idea for this function has been borrowed from a French ffmpeg class located: http://www.phpcs.com/codesource.aspx?ID=45279

File

libraries/phpvideotoolkit/phpvideotoolkit.php5.php, line 929
Libary to access FFmpeg

Class

PHPVideoToolkit

Code

public function parseFileInfo($raw) {
  $data = array();
  $matches = array();

  // grab the duration and bitrate data
  preg_match_all('/Duration: (.*)/', $raw, $matches);
  if (!empty($matches[0])) {
    $line = trim($matches[0][0]);

    // capture any data
    preg_match_all('/(Duration|start|bitrate): ([^,]*)/', $line, $matches);

    // setup the default data
    $data['duration'] = array(
      'timecode' => array(
        'seconds' => array(
          'exact' => -1,
          'excess' => -1,
        ),
        'rounded' => -1,
      ),
    );

    // get the data
    foreach ($matches[1] as $key => $detail) {
      $value = $matches[2][$key];
      switch (strtolower($detail)) {
        case 'duration':
          $data['duration']['timecode']['rounded'] = substr($value, 0, 8);
          $data['duration']['timecode']['frames'] = array();
          $data['duration']['timecode']['frames']['exact'] = $value;
          $data['duration']['timecode']['frames']['excess'] = intval(substr($value, 9));
          break;
        case 'bitrate':
          $data['bitrate'] = strtoupper($value) === 'N/A' ? -1 : intval($value);
          break;
        case 'start':
          $data['duration']['start'] = $value;
          break;
      }
    }
  }

  // match the video stream info
  preg_match('/Stream(.*): Video: (.*)/', $raw, $matches);
  if (count($matches) > 0) {
    $data['video'] = array();

    // get the dimension parts
    preg_match('/([1-9][0-9]*)x([1-9][0-9]*)/', $matches[2], $dimensions_matches);
    $dimensions_value = $dimensions_matches[0];
    $data['video']['dimensions'] = array(
      'width' => floatval($dimensions_matches[1]),
      'height' => floatval($dimensions_matches[2]),
    );

    // get the timebases
    $data['video']['time_bases'] = array();
    preg_match_all('/([0-9\\.k]+) (fps|tbr|tbc|tbn)/', $matches[0], $fps_matches);
    if (count($fps_matches[0]) > 0) {
      foreach ($fps_matches[2] as $key => $abrv) {
        $data['video']['time_bases'][$abrv] = $fps_matches[1][$key];
      }
    }

    // get the video frames per second
    $data['duration']['timecode']['seconds']['total'] = $data['duration']['seconds'] = (double) $this
      ->formatTimecode($data['duration']['timecode']['frames']['exact'], '%hh:%mm:%ss.%ms', '%ss.%ms');
    $fps = isset($data['video']['time_bases']['fps']) === TRUE ? $data['video']['time_bases']['fps'] : (isset($data['video']['time_bases']['tbr']) === TRUE ? $data['video']['time_bases']['tbr'] : FALSE);
    if ($fps !== FALSE) {
      $fps = floatval($fps);
      $data['duration']['timecode']['frames']['frame_rate'] = $data['video']['frame_rate'] = $fps;

      // set the total frame count for the video
      $data['video']['frame_count'] = ceil($data['duration']['seconds'] * $data['video']['frame_rate']);
      $data['duration']['timecode']['frames']['exact'] = $this
        ->formatTimecode($data['video']['frame_count'], '%ft', '%hh:%mm:%ss.%fn', $fps);
      $data['duration']['timecode']['frames']['total'] = $data['video']['frame_count'];
    }
    $fps_value = $fps_matches[0];

    // get the ratios
    preg_match('/\\[PAR ([0-9\\:\\.]+) DAR ([0-9\\:\\.]+)\\]/', $matches[0], $ratio_matches);
    if (count($ratio_matches)) {
      $data['video']['pixel_aspect_ratio'] = $ratio_matches[1];
      $data['video']['display_aspect_ratio'] = $ratio_matches[2];
    }

    // work out the number of frames
    if (isset($data['duration']) === TRUE && isset($data['video']) === TRUE) {

      // set the framecode
      $data['duration']['timecode']['seconds']['excess'] = floatval($data['duration']['seconds']) - floor($data['duration']['seconds']);
      $data['duration']['timecode']['seconds']['exact'] = $this
        ->formatSeconds($data['duration']['seconds'], '%hh:%mm:%ss.%ms');
    }

    // formats should be anything left over, let me know if anything else exists
    $parts = explode(',', $matches[2]);
    $other_parts = array(
      $dimensions_value,
      $fps_value,
    );
    $formats = array();
    foreach ($parts as $key => $part) {
      $part = trim($part);
      if (!in_array($part, $other_parts)) {
        array_push($formats, $part);
      }
    }
    $data['video']['pixel_format'] = $formats[1];
    $data['video']['codec'] = $formats[0];

    // is rotation set?
    preg_match('/rotate\\s*:\\s*(\\d+)/', $raw, $rotate_matches);
    if (count($rotate_matches) > 0) {
      $data['video']['rotate'] = intval($rotate_matches[1]);
    }
  }

  // match the audio stream info
  preg_match('/Stream(.*): Audio: (.*)/', $raw, $matches);
  if (count($matches) > 0) {

    // setup audio values
    $data['audio'] = array(
      'stereo' => -1,
      'sample_rate' => -1,
      'sample_rate' => -1,
    );
    $other_parts = array();

    // get the stereo value
    preg_match('/(stereo|mono)/i', $matches[0], $stereo_matches);
    if (count($stereo_matches)) {
      $data['audio']['stereo'] = $stereo_matches[0];
      array_push($other_parts, $stereo_matches[0]);
    }

    // get the sample_rate
    preg_match('/([0-9]{3,6}) Hz/', $matches[0], $sample_matches);
    if (count($sample_matches)) {
      $data['audio']['sample_rate'] = count($sample_matches) ? floatval($sample_matches[1]) : -1;
      array_push($other_parts, $sample_matches[0]);
    }

    // get the bit rate
    preg_match('/([0-9]{1,3}) kb\\/s/', $matches[0], $bitrate_matches);
    if (count($bitrate_matches)) {
      $data['audio']['bitrate'] = count($bitrate_matches) ? floatval($bitrate_matches[1]) : -1;
      array_push($other_parts, $bitrate_matches[0]);
    }

    // formats should be anything left over, let me know if anything else exists
    $parts = explode(',', $matches[2]);
    $formats = array();
    foreach ($parts as $key => $part) {
      $part = trim($part);
      if (!in_array($part, $other_parts)) {
        array_push($formats, $part);
      }
    }
    $data['audio']['codec'] = $formats[0];

    // if no video is set then no audio frame rate is set
    if ($data['duration']['timecode']['seconds']['exact'] === -1) {
      $exact_timecode = $this
        ->formatTimecode($data['duration']['timecode']['frames']['exact'], '%hh:%mm:%ss.%fn', '%hh:%mm:%ss.%ms', 1000);
      $data['duration']['timecode']['seconds'] = array(
        'exact' => $exact_timecode,
        'excess' => intval(substr($exact_timecode, 8)),
        'total' => $this
          ->formatTimecode($data['duration']['timecode']['frames']['exact'], '%hh:%mm:%ss.%fn', '%ss.%ms', 1000),
      );
      $data['duration']['timecode']['frames']['frame_rate'] = 1000;
      $data['duration']['seconds'] = $data['duration']['timecode']['seconds']['total'];
    }
  }
  return $data;
}