photo/app/Media/QuickTime.php

121 lines
2.8 KiB
PHP

<?php
namespace App\Media;
use Illuminate\Support\Collection;
use App\Media\QuickTime\Atoms\{mdat,moov,Unknown};
use App\Traits\FindQuicktimeAtoms;
// https://developer.apple.com/documentation/quicktime-file-format/quicktime_movie_files
class QuickTime extends Base {
use FindQuicktimeAtoms;
private const LOGKEY = 'MFQ';
private Collection $atoms;
private const atom_classes = 'App\\Media\\QuickTime\\Atoms\\';
public function __construct(string $filename,string $type)
{
parent::__construct($filename,$type);
// Parse the atoms
$this->atoms = $this->get_atoms(self::atom_classes,Unknown::class,0,$this->filesize);
}
public function __get(string $key): mixed
{
switch ($key) {
case 'audio_channels':
case 'audio_codec':
case 'audio_samplerate':
return $this->getAudioAtoms()
->map(fn($item)=>$item->find_atoms(moov\trak\mdia\minf\stbl\stsd::class,1))
->flatten()
->map(fn($item)=>$item->{$key})
->join(',');
// Signatures are calculated by the sha of the MDAT atom.
case 'signature':
$atom = $this->find_atoms(mdat::class,1);
return $atom->signature;
// Creation Time is in the MOOV/MVHD atom
case 'creation_date':
case 'duration':
case 'preferred_rate':
case 'preferred_volume':
// Height/Width is in the moov/trak/tkhd attom
case 'height':
case 'width':
$atom = $this->find_atoms(moov::class,1);
return $atom->{$key};
case 'gps_altitude':
case 'gps_lat':
case 'gps_lon':
$atom = $this->find_atoms(moov::class,1)
->find_atoms(moov\meta::class,1);
return $atom->{$key};
case 'time_scale':
$atom = $this->find_atoms(moov\mvhd::class,1);
return $atom->{$key};
case 'type':
return parent::__get($key);
case 'video_codec':
return $this->getVideoAtoms()
->map(fn($item)=>$item->find_atoms(moov\trak\mdia\minf\stbl\stsd::class,1))
->flatten()
->map(fn($item)=>$item->{$key})
->join(',');
case 'video_framerate':
$atom = $this->getVideoAtoms()
->map(fn($item)=>$item->find_atoms(moov\trak\mdia\minf\stbl\stts::class,1))
->pop();
return $atom->frame_rate($this->time_scale);
default:
throw new \Exception('Unknown key: '.$key);
}
}
/**
* Find all the audio track atoms
*
* Audio atoms are in moov/trak/mdia/minf
*
* @return Collection
* @throws \Exception
*/
public function getAudioAtoms(): Collection
{
return $this->find_atoms(moov\trak\mdia\minf::class)
->filter(fn($item)=>$item->type==='soun');
}
/**
* Find all the video track atoms
*
* Audio atoms are in moov/trak/mdia/minf
*
* @return Collection
* @throws \Exception
*/
public function getVideoAtoms(): Collection
{
return $this->find_atoms(moov\trak\mdia\minf::class)
->filter(fn($item)=>$item->type==='vide');
}
}