PHP函数获取MP3的持续时间

PHP函数获取MP3的持续时间,php,mp3,Php,Mp3,是否有任何PHP函数,将给我的MP3的持续时间。我查看了id3函数,但我没有看到持续时间的任何内容,除此之外,id3是一种标签,它不会出现在所有MP3中,因此使用它没有任何意义。安装getid3,但如果您只需要持续时间,您可以删除除以下模块以外的所有模块: module.audio.mp3.php module.tag.id3v1.php module.tag.apetag.php module.tag.id3v2.php 使用如下代码访问持续时间: $getID3 = new getID3

是否有任何PHP函数,将给我的MP3的持续时间。我查看了id3函数,但我没有看到持续时间的任何内容,除此之外,id3是一种标签,它不会出现在所有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

上获取它应该对您有用,请注意getduration函数:

没有本机php函数可以执行此操作

根据您的服务器环境,您可以使用工具,如


MP3长度不会存储在任何地方(以“普通”MP3格式),因为MP3被设计为“拆分”为帧,并且这些帧将保持可播放状态


如果您没有可以依赖的ID标记,那么您需要做的是(有一些工具和PHP类可以这样做)读取整个MP3文件并对每个帧的持续时间求和。

您可以使用ffmpeg获得MP3或许多其他音频/视频文件的持续时间

  • 在服务器中安装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;
    
        }
    
  • 我希望这对您有所帮助。

    
    
    <?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";
    
    ?>
    

    我已经度过了这么多时间,但是没有getID3()来获取音频文件的持续时间是不可能的

    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);
        ?>
    

    最后,我用自己的计算开发了一个解决方案。此解决方案最适用于mp3WAV文件格式。然而,预计精度会有微小变化。解决方案在PHP中。我从中得到一点线索


    如前所述,我为mp3WAV文件提供了一个解决方案,现在这个解决方案专门针对唯一的WAV文件,它的精度更高,但评估时间比前一个解决方案更长

    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);
    

    如果安装了FFMpeg,使用FFProbe获取持续时间非常简单

    $filepath = 'example.mp3';
    $ffprobe = \FFMpeg\FFProbe::create();
    $duration = $ffprobe->format($filepath)->get('duration');
    
    echo gmdate('H:i:s', $duration);
    

    好的,可以使用PHP5而不是PHP4,因此不确定您是否可以获得更多“现代”的作品,但有时它会返回严重性:警告-->fseek():stream不支持Seeking甚至有一个Drupal模块用于此,上的文档非常棒!WordPress(4.7.5)在核心中包含了getID3的1.9.9-20141121版,仅供参考。对于那些无法查看的远程URL来说,这似乎是一种很好的思考方式。这对我来说是一个很好的答案,因为它不需要加载整个文件来获得持续时间。并且可以用于远程文件。
    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);
    
    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);
    
    $filepath = 'example.mp3';
    $ffprobe = \FFMpeg\FFProbe::create();
    $duration = $ffprobe->format($filepath)->get('duration');
    
    echo gmdate('H:i:s', $duration);