$real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']);
if ($real_filesize === false) {
unset($this->info['filesize']);
throw new getid3_exception('Unable to determine actual filesize. File is most likely larger than '.round(PHP_INT_MAX / 1073741824).'GB and is not supported by PHP.');
} elseif (getid3_lib::intValueSupported($real_filesize)) {
unset($this->info['filesize']);
throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org');
$this->info['filesize'] = $real_filesize;
$this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.');
$this->error($e->getMessage());
* @param string $filename
* @param string $original_filename
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
if (!$this->openfile($filename, $filesize, $fp)) {
foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
$option_tag = 'option_tag_'.$tag_name;
if ($this->$option_tag) {
$this->include_module('tag.'.$tag_name);
$tag_class = 'getid3_'.$tag_name;
$tag = new $tag_class($this);
catch (getid3_exception $e) {
if (isset($this->info['id3v2']['tag_offset_start'])) {
$this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']);
foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
if (isset($this->info[$tag_key]['tag_offset_start'])) {
$this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']);
// ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
if (!$this->option_tag_id3v2) {
$header = fread($this->fp, 10);
if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
$this->info['id3v2']['header'] = true;
$this->info['id3v2']['majorversion'] = ord($header[3]);
$this->info['id3v2']['minorversion'] = ord($header[4]);
$this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
fseek($this->fp, $this->info['avdataoffset']);
$formattest = fread($this->fp, 32774);
$determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
// unable to determine file format
if (!$determined_format) {
return $this->error('unable to determine file format');
// check for illegal ID3 tags
if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
if ($determined_format['fail_id3'] === 'ERROR') {
return $this->error('ID3 tags not allowed on this file type.');
} elseif ($determined_format['fail_id3'] === 'WARNING') {
$this->warning('ID3 tags not allowed on this file type.');
// check for illegal APE tags
if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
if ($determined_format['fail_ape'] === 'ERROR') {
return $this->error('APE tags not allowed on this file type.');
} elseif ($determined_format['fail_ape'] === 'WARNING') {
$this->warning('APE tags not allowed on this file type.');
$this->info['mime_type'] = $determined_format['mime_type'];
// supported format signature pattern detected, but module deleted
if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) {
return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
// module requires mb_convert_encoding/iconv support
// Check encoding/iconv support
if (!empty($determined_format['iconv_req']) && !function_exists('mb_convert_encoding') && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
$errormessage = 'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
if (GETID3_OS_ISWINDOWS) {
$errormessage .= 'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32';
$errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch';
return $this->error($errormessage);
include_once(GETID3_INCLUDEPATH.$determined_format['include']);
// instantiate module class
$class_name = 'getid3_'.$determined_format['module'];
if (!class_exists($class_name)) {
return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.');
$class = new $class_name($this);
// process all tags - copy to 'tags' and convert charsets
if ($this->option_tags_process) {
// perform more calculations
if ($this->option_extra_info) {
$this->ChannelsBitratePlaytimeCalculations();
$this->CalculateCompressionRatioVideo();
$this->CalculateCompressionRatioAudio();
$this->CalculateReplayGain();
$this->ProcessAudioStreams();
// get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
if ($this->option_md5_data) {
// do not calc md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
$this->getHashdata('md5');
// get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
if ($this->option_sha1_data) {
$this->getHashdata('sha1');
$this->error('Caught exception: '.$e->getMessage());
public function error($message) {
if (!isset($this->info['error'])) {
$this->info['error'] = array();
$this->info['error'][] = $message;
public function warning($message) {
$this->info['warning'][] = $message;
private function CleanUp() {
// remove possible empty keys
$AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
foreach ($AVpossibleEmptyKeys as $dummy => $key) {
if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
unset($this->info['audio'][$key]);
if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
unset($this->info['video'][$key]);
// remove empty root keys
if (!empty($this->info)) {
foreach ($this->info as $key => $value) {
if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) {
unset($this->info[$key]);
// remove meaningless entries from unknown-format files
if (empty($this->info['fileformat'])) {
if (isset($this->info['avdataoffset'])) {
unset($this->info['avdataoffset']);
if (isset($this->info['avdataend'])) {
unset($this->info['avdataend']);
// remove possible duplicated identical entries
if (!empty($this->info['error'])) {
$this->info['error'] = array_values(array_unique($this->info['error']));
if (!empty($this->info['warning'])) {
$this->info['warning'] = array_values(array_unique($this->info['warning']));
// remove "global variable" type keys
unset($this->info['php_memory_limit']);
* Return array containing information about all supported formats.
public function GetFileFormatArray() {
static $format_info = array();
if (empty($format_info)) {
// AC-3 - audio - Dolby AC-3 / Dolby Digital
'pattern' => '^\\x0B\\x77',
'mime_type' => 'audio/ac3',
// AAC - audio - Advanced Audio Coding (AAC) - ADIF format
'mime_type' => 'audio/aac',
// AA - audio - Audible Audiobook
'pattern' => '^.{4}\\x57\\x90\\x75\\x36',
'mime_type' => 'audio/audible',
// AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
'mime_type' => 'audio/aac',
// AU - audio - NeXT/Sun AUdio (AU)
'mime_type' => 'audio/basic',
// AMR - audio - Adaptive Multi Rate
'pattern' => '^\\x23\\x21AMR\\x0A', // #!AMR[0A]
'mime_type' => 'audio/amr',
// AVR - audio - Audio Visual Research
'mime_type' => 'application/octet-stream',
// BONK - audio - Bonk v0.9+
'pattern' => '^\\x00(BONK|INFO|META| ID3)',
'mime_type' => 'audio/xmms-bonk',
// DSF - audio - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital
'pattern' => '^DSD ', // including trailing space: 44 53 44 20
'mime_type' => 'audio/dsd',
// DSS - audio - Digital Speech Standard
'pattern' => '^[\\x02-\\x08]ds[s2]',
'mime_type' => 'application/octet-stream',
// DSDIFF - audio - Direct Stream Digital Interchange File Format
'mime_type' => 'audio/dsd',
// DTS - audio - Dolby Theatre System
'pattern' => '^\\x7F\\xFE\\x80\\x01',
'mime_type' => 'audio/dts',
// FLAC - audio - Free Lossless Audio Codec
'mime_type' => 'audio/flac',
// LA - audio - Lossless Audio (LA)
'pattern' => '^LA0[2-4]',
'mime_type' => 'application/octet-stream',
// LPAC - audio - Lossless Predictive Audio Compression (LPAC)
'mime_type' => 'application/octet-stream',
// MIDI - audio - MIDI (Musical Instrument Digital Interface)
'mime_type' => 'audio/midi',
// MAC - audio - Monkey's Audio Compressor
'mime_type' => 'audio/x-monkeys-audio',
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
// // MOD - audio - MODule (assorted sub-formats)
// 'pattern' => '^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)',
// 'mime_type' => 'audio/mod',
// MOD - audio - MODule (Impulse Tracker)
'mime_type' => 'audio/it',
// MOD - audio - MODule (eXtended Module, various sub-formats)
'pattern' => '^Extended Module',
'mime_type' => 'audio/xm',
// MOD - audio - MODule (ScreamTracker)
'pattern' => '^.{44}SCRM',
'mime_type' => 'audio/s3m',
// MPC - audio - Musepack / MPEGplus
'pattern' => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])',
'mime_type' => 'audio/x-musepack',
// MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
'pattern' => '^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\x0B\\x10-\\x1B\\x20-\\x2B\\x30-\\x3B\\x40-\\x4B\\x50-\\x5B\\x60-\\x6B\\x70-\\x7B\\x80-\\x8B\\x90-\\x9B\\xA0-\\xAB\\xB0-\\xBB\\xC0-\\xCB\\xD0-\\xDB\\xE0-\\xEB\\xF0-\\xFB]',
'mime_type' => 'audio/mpeg',
// OFR - audio - OptimFROG
'pattern' => '^(\\*RIFF|OFR)',
'mime_type' => 'application/octet-stream',
// RKAU - audio - RKive AUdio compressor
'mime_type' => 'application/octet-stream',
'mime_type' => 'audio/xmms-shn',
// TAK - audio - Tom's lossless Audio Kompressor
'mime_type' => 'application/octet-stream',