PHP函数获得MP3持续时间
有什么PHPfunction,会给我的MP3持续时间。 我看着ID 3的function,但我没有看到有任何东西持续时间,除此之外,ID3是一种标签,这将不会在所有的MP3,所以使用这是没有任何意义的。
这应该为你工作,注意getdurationfunction: http ://www.zedwood.com/article/127/php-calculate-duration-of-mp3
安装getid3,但如果只需要持续时间,则可以删除除这些模块以外的所有模块:
- module.audio.mp3.php
- module.tag.id3v1.php
- module.tag.apetag.php
- module.tag.id3v2.php
用这样的代码访问持续时间:
$getID3 = new getID3; $ThisFileInfo = $getID3->analyze($pathName); $len= @$ThisFileInfo['playtime_string']; // playtime in minutes:seconds, formatted string
在Sourceforge获取它
我已经通过了这么多的时间,但没有getID3( http://getid3.sourceforge.net/ )获取audio文件的时间不可能。
1)首先使用下面的链接下载getID3的库:
https://github.com/JamesHeinrich/getID3/archive/master.zip
2)尝试下面的代码:
<?php include("getid3/getid3.php"); $filename = 'bcd4ecc6bf521da9b9a2d8b9616d1505.wav'; $getID3 = new getID3; $file = $getID3->analyze($filename); $playtime_seconds = $file['playtime_seconds']; echo gmdate("H:i:s", $playtime_seconds); ?>
您可以使用ffmpeg来获取mp3或其他audio/video文件的持续时间。
- 在你的服务器上安装ffmpeg。
-
确保php的shell_exec在你的php中不受限制。
// Discriminate only the audio/video files you want if(preg_match('/[^?#]+\.(?:wma|mp3|wav|mp4)/', strtolower($file))){ $filepath = /* your file path */; // execute ffmpeg form linux shell and grab duration from output $result = shell_exec("ffmpeg -i ".$filepath.' 2>&1 | grep -o \'Duration: [0-9:.]*\''); $duration = str_replace('Duration: ', '', $result); // 00:05:03.25 //get the duration in seconds $timeArr = preg_split('/:/', str_replace('s', '', $duration[0])); $t = $this->_times[$file] = (($timeArr[3])? $timeArr[3]*1 + $timeArr[2] * 60 + $timeArr[1] * 60 * 60 : $timeArr[2] + $timeArr[1] * 60)*1000; }
没有原生的PHPfunction来做到这一点。
根据您的服务器环境,您可以使用诸如MP3Info之类的工具。
$length = shell_exec('mp3info -p "%S" sample.mp3'); // total time in seconds
<?php class MP3File { protected $filename; public function __construct($filename) { $this->filename = $filename; } public static function formatTime($duration) //as hh:mm:ss { //return sprintf("%d:%02d", $duration/60, $duration%60); $hours = floor($duration / 3600); $minutes = floor( ($duration - ($hours * 3600)) / 60); $seconds = $duration - ($hours * 3600) - ($minutes * 60); return sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds); } //Read first mp3 frame only... use for CBR constant bit rate MP3s public function getDurationEstimate() { return $this->getDuration($use_cbr_estimate=true); } //Read entire file, frame by frame... ie: Variable Bit Rate (VBR) public function getDuration($use_cbr_estimate=false) { $fd = fopen($this->filename, "rb"); $duration=0; $block = fread($fd, 100); $offset = $this->skipID3v2Tag($block); fseek($fd, $offset, SEEK_SET); while (!feof($fd)) { $block = fread($fd, 10); if (strlen($block)<10) { break; } //looking for 1111 1111 111 (frame synchronization bits) else if ($block[0]=="\xff" && (ord($block[1])&0xe0) ) { $info = self::parseFrameHeader(substr($block, 0, 4)); if (empty($info['Framesize'])) { return $duration; } //some corrupt mp3 files fseek($fd, $info['Framesize']-10, SEEK_CUR); $duration += ( $info['Samples'] / $info['Sampling Rate'] ); } else if (substr($block, 0, 3)=='TAG') { fseek($fd, 128-10, SEEK_CUR);//skip over id3v1 tag size } else { fseek($fd, -9, SEEK_CUR); } if ($use_cbr_estimate && !empty($info)) { return $this->estimateDuration($info['Bitrate'],$offset); } } return round($duration); } private function estimateDuration($bitrate,$offset) { $kbps = ($bitrate*1000)/8; $datasize = filesize($this->filename) - $offset; return round($datasize / $kbps); } private function skipID3v2Tag(&$block) { if (substr($block, 0,3)=="ID3") { $id3v2_major_version = ord($block[3]); $id3v2_minor_version = ord($block[4]); $id3v2_flags = ord($block[5]); $flag_unsynchronisation = $id3v2_flags & 0x80 ? 1 : 0; $flag_extended_header = $id3v2_flags & 0x40 ? 1 : 0; $flag_experimental_ind = $id3v2_flags & 0x20 ? 1 : 0; $flag_footer_present = $id3v2_flags & 0x10 ? 1 : 0; $z0 = ord($block[6]); $z1 = ord($block[7]); $z2 = ord($block[8]); $z3 = ord($block[9]); if ( (($z0&0x80)==0) && (($z1&0x80)==0) && (($z2&0x80)==0) && (($z3&0x80)==0) ) { $header_size = 10; $tag_size = (($z0&0x7f) * 2097152) + (($z1&0x7f) * 16384) + (($z2&0x7f) * 128) + ($z3&0x7f); $footer_size = $flag_footer_present ? 10 : 0; return $header_size + $tag_size + $footer_size;//bytes to skip } } return 0; } public static function parseFrameHeader($fourbytes) { static $versions = array( 0x0=>'2.5',0x1=>'x',0x2=>'2',0x3=>'1', // x=>'reserved' ); static $layers = array( 0x0=>'x',0x1=>'3',0x2=>'2',0x3=>'1', // x=>'reserved' ); static $bitrates = array( 'V1L1'=>array(0,32,64,96,128,160,192,224,256,288,320,352,384,416,448), 'V1L2'=>array(0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384), 'V1L3'=>array(0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320), 'V2L1'=>array(0,32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256), 'V2L2'=>array(0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160), 'V2L3'=>array(0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160), ); static $sample_rates = array( '1' => array(44100,48000,32000), '2' => array(22050,24000,16000), '2.5' => array(11025,12000, 8000), ); static $samples = array( 1 => array( 1 => 384, 2 =>1152, 3 =>1152, ), //MPEGv1, Layers 1,2,3 2 => array( 1 => 384, 2 =>1152, 3 => 576, ), //MPEGv2/2.5, Layers 1,2,3 ); //$b0=ord($fourbytes[0]);//will always be 0xff $b1=ord($fourbytes[1]); $b2=ord($fourbytes[2]); $b3=ord($fourbytes[3]); $version_bits = ($b1 & 0x18) >> 3; $version = $versions[$version_bits]; $simple_version = ($version=='2.5' ? 2 : $version); $layer_bits = ($b1 & 0x06) >> 1; $layer = $layers[$layer_bits]; $protection_bit = ($b1 & 0x01); $bitrate_key = sprintf('V%dL%d', $simple_version , $layer); $bitrate_idx = ($b2 & 0xf0) >> 4; $bitrate = isset($bitrates[$bitrate_key][$bitrate_idx]) ? $bitrates[$bitrate_key][$bitrate_idx] : 0; $sample_rate_idx = ($b2 & 0x0c) >> 2;//0xc => b1100 $sample_rate = isset($sample_rates[$version][$sample_rate_idx]) ? $sample_rates[$version][$sample_rate_idx] : 0; $padding_bit = ($b2 & 0x02) >> 1; $private_bit = ($b2 & 0x01); $channel_mode_bits = ($b3 & 0xc0) >> 6; $mode_extension_bits = ($b3 & 0x30) >> 4; $copyright_bit = ($b3 & 0x08) >> 3; $original_bit = ($b3 & 0x04) >> 2; $emphasis = ($b3 & 0x03); $info = array(); $info['Version'] = $version;//MPEGVersion $info['Layer'] = $layer; //$info['Protection Bit'] = $protection_bit; //0=> protected by 2 byte CRC, 1=>not protected $info['Bitrate'] = $bitrate; $info['Sampling Rate'] = $sample_rate; $info['Framesize'] = self::framesize($layer, $bitrate, $sample_rate, $padding_bit); $info['Samples'] = $samples[$simple_version][$layer]; return $info; } private static function framesize($layer, $bitrate,$sample_rate,$padding_bit) { if ($layer==1) return intval(((12 * $bitrate*1000 /$sample_rate) + $padding_bit) * 4); else //layer 2, 3 return intval(((144 * $bitrate*1000)/$sample_rate) + $padding_bit); } } ?> <?php $mp3file = new MP3File("Chal_Halke.mp3");//http://www.npr.org/rss/podcast.php?id=510282 $duration1 = $mp3file->getDurationEstimate();//(faster) for CBR only $duration2 = $mp3file->getDuration();//(slower) for VBR (or CBR) echo "duration: $duration1 seconds"."\n"; ?>
由于MP3被devise为“分割”成帧,并且这些帧将保持可播放,所以MP3长度不存储在任何地方(以“普通”MP3格式)。
http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
如果你没有ID标签,你需要做什么(有工具和PHP类这样做)是读取整个MP3文件,并总结每个帧的持续时间。
$getID3 = new getID3; $ThisFileInfo = $getID3->analyze($pathName); // playtime in minutes:seconds, formatted string $len = @$ThisFileInfo['playtime_string']; //don't get playtime_string, but get playtime_seconds $len = @$ThisFileInfo['playtime_seconds']*1000; //*1000 as calculate millisecond
我希望这可以帮助你。
最后,我用自己的计算开发了一个解决scheme。 此解决scheme适用于mp3和WAV文件格式。 然而,预计会有微小的精度变化 解决scheme是在PHP中 。 我从WAV中得到了一些线索
function calculateFileSize($file){ $ratio = 16000; //bytespersec if (!$file) { exit("Verify file name and it's path"); } $file_size = filesize($file); if (!$file_size) exit("Verify file, something wrong with your file"); $duration = ($file_size / $ratio); $minutes = floor($duration / 60); $seconds = $duration - ($minutes * 60); $seconds = round($seconds); echo "$minutes:$seconds minutes"; } $file = 'apple-classic.mp3'; //Enter File Name mp3/wav calculateFileSize($file);
如前所述,我提供了一个解决scheme的MP3和WAV文件,现在这个解决scheme是专门为唯一的WAV文件具有更高的精度,但比较早的解决scheme具有更长的评估时间。
function calculateWavDuration( $file ) { $fp = fopen($file, 'r'); if (fread($fp, 4) == "RIFF") { fseek($fp, 20); $raw_header = fread($fp, 16); $header = unpack('vtype/vchannels/Vsamplerate/Vbytespersec/valignment/vbits', $raw_header); $pos = ftell($fp); while (fread($fp, 4) != "data" && !feof($fp)) { $pos++; fseek($fp, $pos); } $raw_header = fread($fp, 4); $data = unpack('Vdatasize', $raw_header); $sec = $data[datasize] / $header[bytespersec]; $minutes = intval(($sec / 60) % 60); $seconds = intval($sec % 60); return str_pad($minutes, 2, "0", STR_PAD_LEFT) . ":" . str_pad($seconds, 2, "0", STR_PAD_LEFT); } } $file = '1.wav'; //Enter File wav calculateWavDuration($file);