Created
May 12, 2018 19:34
-
-
Save NinoSkopac/fdf1c88da6d9d57c852eca3a688f3310 to your computer and use it in GitHub Desktop.
Get correct OGG Vorbis metadata using ffprobe (requires getID3 library)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Created by PhpStorm. | |
* User: ninoskopac | |
* Date: 10/05/2018 | |
* Time: 07:01 | |
*/ | |
declare(strict_types=1); | |
namespace Read2Me\Synthesis; | |
use Symfony\Component\Process\Process; | |
final class AudioMeta implements AudioMetaInterface | |
{ | |
/** @var \SplFileObject */ | |
private $file; | |
/** @var array */ | |
private $data; | |
public function __construct(\SplFileObject $file) | |
{ | |
$getId3 = new \getID3(); | |
$this->file = $file; | |
$this->data = $getId3->analyze($this->file->getRealPath()); | |
// getID3 returns invalid data for Ogg_vorbis, so have to do it | |
// manually using FFMpeg//ffprobe. yayness | |
if ($this->file->getExtension() == 'ogg') | |
$this->ffprobe(); | |
} | |
/** | |
* Override the following properties: | |
* - duration in seconds | |
* - duration in human readable | |
* - sample rate | |
* - bitrate (ffprobe returns this in kb/s, R2M stores it in b/s) | |
*/ | |
private function ffprobe(): void { | |
$cmd = sprintf('ffprobe -i %s -show_format', escapeshellarg($this->file->getRealPath())); | |
$process = new Process($cmd); | |
$process->mustRun(); | |
// fprobe returns a lot of useful data as info into stderr | |
// https://trac.ffmpeg.org/ticket/2226 | |
// https://trac.ffmpeg.org/ticket/5020 | |
$info = $process->getErrorOutput(); | |
$format = $process->getOutput(); | |
preg_match('/duration\=(.+)/', $format, $duration); | |
preg_match('/Duration\: ((\d{2})\:(\d{2})\:(\d{2}))/', $info, $durationHuman); | |
preg_match('/\, (.+) Hz/', $info, $sampleRate); | |
preg_match('/bitrate\: (.+) kb\/s/', $info, $bitrate); | |
$duration = (int) ceil($duration[1]); | |
[, $durationHumanHms, $durationHours, $durationMinutes, $durationSeconds] = $durationHuman; | |
if ($durationHours == '00') | |
$durationHuman = sprintf('%d:%d', $durationMinutes, $durationSeconds); | |
else | |
$durationHuman = $durationHumanHms; | |
$sampleRate = $sampleRate[1]; | |
$bitrate = ((int) $bitrate[1]) * 1000; | |
$this->data['playtime_seconds'] = $duration; | |
$this->data['playtime_string'] = $durationHuman; | |
$this->data['audio']['sample_rate'] = (int) $sampleRate; | |
$this->data['audio']['bitrate'] = $bitrate; | |
} | |
public function getLength(): int | |
{ | |
return (int) ceil($this->data['playtime_seconds']); | |
} | |
public function getPlaytime(): string | |
{ | |
return $this->data['playtime_string']; | |
} | |
public function getFilesize(): int | |
{ | |
return $this->data['filesize']; | |
} | |
public function getFormat(): string | |
{ | |
return $this->data['fileformat']; | |
} | |
public function getSampleRate(): int | |
{ | |
return $this->data['audio']['sample_rate']; | |
} | |
public function getBitrate(): int | |
{ | |
return (int) $this->data['audio']['bitrate']; | |
} | |
public function getMime(): string | |
{ | |
return strpos($this->data['mime_type'], ';') !== false ? | |
strstr($this->data['mime_type'], ';', true) | |
: | |
$this->data['mime_type']; | |
} | |
public function toArray(): array { | |
return [ | |
'length' => $this->getLength(), | |
'playtime' => $this->getPlaytime(), | |
'filesize' => $this->getFilesize(), | |
'format' => $this->getFormat(), | |
'sample_rate' => $this->getSampleRate(), | |
'bitrate' => $this->getBitrate(), | |
'mime' => $this->getMime() | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
here's the interface