-2

i want to equal youtube playlist all videos time from this link http://gdata.youtube.com/feeds/api/playlists/PLCK7NnIZXn7gGU5wDy9iKOK6T2fwtGL6l. here have time code like this time='00:05:11.500' .. i want to get all videos time from php then its show like this from php

show it like this : 2:10:50 (2=hours,10=minutes,50=seconds)

i want to variable from php for like this one. plzz help for this post thanks. i tried to do that.. but i can do this.. if someone can plz help me.. if have 4 videos, want to equal all videos time and then want to show all duration from php only

user3501407
  • 447
  • 6
  • 21

2 Answers2

6

Ok, here's an answer that solves the problem assuming you have no code whatsoever, and no intention of trying do experiment yourself.

You will probably not be able to use this for anything else than the exact problem described: adding all the durations of this feed together and displaying it as hours:minutes:seconds

<?php

$total_seconds = 0;

$dom = new DOMDocument();
$dom->loadXML(file_get_contents('http://gdata.youtube.com/feeds/api/playlists/PLCK7NnIZXn7gGU5wDy9iKOK6T2fwtGL6l'));

$xpath = new DOMXPath($dom);
foreach ($xpath->query('//yt:duration/@seconds') as $duration) {
    $total_seconds += (int) $duration->value;
}

Then you display $total_seconds in your format. Here's two options:

assuming that hours will never be larger than 24

echo gmdate("H:i:s", $total_seconds);

allowing total time to be larger than 24 hours

echo (int) ($total_seconds / 3600) . ':' . (int) ($total_seconds / 60) % 60 . ':' . $total_seconds % 60;

Keep in mind: This code does exactly ZERO error checking. Things that can go wrong:

  • The PHP configuration may not allow http stream wrapper
  • The PHP build might not have Dom enabled
  • The XML feed may be unavailable
  • The XML feed might not contain any entries
Community
  • 1
  • 1
Ramon de la Fuente
  • 8,044
  • 3
  • 32
  • 31
3

EDIT: I took a closer look at the feed, and it seems the "time" entries are just pointers for the thumbnails. The actual duration for a video is set in seconds <yt:duration seconds='667'/> so you could just add them together as integers and then use the DateTime class to convert to whatever your format is. Example here.

END EDIT

First of all, to get all the times, you could need an atom feed reader in PHP. There are plenty out there. Do not try to parse the XML, ATOM is a well known standard that should be easily used (if you really only want the times, you could go with an xpath query).

Now that you have all the times at your disposal, you need a way to add them up easily, preferably without messing with nested loops and if-statements.

Here's a class that represents a single time entry for a single video:

final class Duration
{
    private $hours;
    private $minutes;
    private $seconds;
    private $centis;

    /* we don't want any Durations not created with a create function */
    private function __construct() {}

    public static function fromString($input = '00:00:00.000') {
        $values = self::valuesFromString($input);

        return self::fromValues($values['hours'], $values['minutes'], $values['seconds'], $values['centis']);
    }

    public function addString($string) {
        $duration = self::fromString($string);
        return $this->addDuration($duration);
    }

    public function addDuration(Duration $duration) {
        // add the durations, and return a new duration;
        $values = self::valuesFromString((string) $duration);

        // adding logic here
        $centis  = $values['centis'] + $this->centis;
        $this->fixValue($centis, 1000, $values['seconds']);

        $seconds = $values['seconds'] + $this->seconds;
        $this->fixValue($seconds, 60, $values['minutes']);

        $minutes = $values['minutes'] + $this->minutes;
        $this->fixValue($minutes, 60, $values['hours']);

        $hours   = $values['hours'] + $this->hours;

        return self::fromValues($hours, $minutes, $seconds, $centis);
    }

    public function __toString() {
        return str_pad($this->hours,2,'0',STR_PAD_LEFT) . ':'
               . str_pad($this->minutes,2,'0',STR_PAD_LEFT) . ':'
               . str_pad($this->seconds,2,'0',STR_PAD_LEFT) . '.'
               . str_pad($this->centis,3,'0',STR_PAD_LEFT);
    }

    public function toValues() {
        return self::valuesFromString($this);
    }

    private static function valuesFromString($input) {
        if (1 !== preg_match('/(?<hours>[0-9]{2}):(?<minutes>([0-5]{1}[0-9]{1})):(?<seconds>[0-5]{1}[0-9]{1}).(?<centis>[0-9]{3})/', $input, $matches)) {
            throw new InvalidArgumentException('Invalid input string (should be 01:00:00.000): ' . $input);
        }

        return array(
                'hours' => (int) $matches['hours'],
                'minutes' => (int) $matches['minutes'],
                'seconds' => (int) $matches['seconds'],
                'centis' => (int) $matches['centis']
            );
    }

    private static function fromValues($hours = 0, $minutes = 0, $seconds = 0, $centis = 0) {
        $duration = new Duration();
        $duration->hours = $hours;
        $duration->minutes = $minutes;
        $duration->seconds = $seconds;
        $duration->centis = $centis;

        return $duration;
    }

    private function fixValue(&$input, $max, &$nextUp) {
        if ($input >= $max) {
            $input -= $max;
            $nextUp += 1;
        }
    }
}

You can create a new Duration only by calling the static factory fromString(), and that accepts only strings in the form "00:00:00.000" (hours:minutes:seconds.milliseconds):

$duration = Duration::fromString('00:04:16.250');

Next, you can add another string or an actual duration object, to create a new Duration:

$newDuration = $duration->addString('00:04:16.250');
$newDuration = $duration->addDuration($duration);

The Duration object will output it's own duration string in the format '00:00:00.000':

echo $duration;

// Gives
00:04:16.250

Or, if you're interested in the separate values, you can get them like so:

print_r($duration->toValues());

// Gives
Array
(
    [hours] => 0
    [minutes] => 4
    [seconds] => 16
    [milliseconds] => 250
)

Final example for using this in a loop to get the total video time:

$allTimes = array(
    '00:30:05:250',
    '01:24:38:250',
    '00:07:01:750'
);

$d = Duration::fromString();
foreach ($allTimes as $time) {
    $d = $d->addString($time);
}

echo $d . "\n";
print_r($d->toValues());

// Gives
02:01:45.250
Array
(
    [hours] => 2
    [minutes] => 1
    [seconds] => 45
    [milliseconds] => 250
)

For questions on why I used a final class with private constructor:

I wrote this as an exercise for myself, following Mathias Veraes's blog post on "named constructors".

Also, I couldn't resist adding his "TestFrameworkInATweet" as well:

function it($m,$p){echo ($p?'✔︎':'✘')." It $m\n"; if(!$p){$GLOBALS['f']=1;}}function done(){if(@$GLOBALS['f'])die(1);}
function throws($exp,Closure $cb){try{$cb();}catch(Exception $e){return $e instanceof $exp;}return false;}

it('should be an empty duration from string', Duration::fromString() == '00:00:00.000');
it('should throw an exception with invalid input string', throws("InvalidArgumentException", function () { Duration::fromString('invalid'); }));
it('should throw an exception with invalid seconds input string', throws("InvalidArgumentException", function () { Duration::fromString('00:00:61:000'); }));
it('should throw an exception with invalid minutes input string', throws("InvalidArgumentException", function () { Duration::fromString('00:61:00:000'); }));
it('should add milliseconds to seconds', Duration::fromString('00:00:00.999')->addString('00:00:00.002') == Duration::fromString('00:00:01.001'));
it('should add seconds to minutes', Duration::fromString('00:00:59.000')->addString('00:00:02.000') == Duration::fromString('00:01:01.000'));
it('should add minutes to hours', Duration::fromString('00:59:00.000')->addString('00:02:00.000') == Duration::fromString('01:01:00.000'));
it('should add all levels up', Duration::fromString('00:59:59.999')->addString('00:01:01.002') == Duration::fromString('01:01:01.001'));
$duration = Duration::fromString('00:00:01.500');
it('should add a Duration', $duration->addDuration($duration) == '00:00:03.000');
Community
  • 1
  • 1
Ramon de la Fuente
  • 8,044
  • 3
  • 32
  • 31