2013-01-12 258 views
3

我需要構建一個將mp3文件轉換爲波形圖像的網頁腳本,並且需要我came across this website使用php生成mp3波形

我已經將PHP文件和.dll和.exe文件從LAMB上傳到我的網站(由主機怪物託管)。

但是,當我嘗試上傳網站上的MP3文件時,它只是生成一個黑色的圖像,而不是波形圖像。

我對PHP知之甚少,所以我並不完全知道錯在哪裏,但我猜測它與程序的上傳部分有關。

有人能告訴我什麼是錯的,我怎麼能克服它?

以下是php代碼原樣(也可用in this repository on GitHub)。

<?php 

    ini_set("max_execution_time", "30000"); 

    // how much detail we want. Larger number means less detail 
    // (basically, how many bytes/frames to skip processing) 
    // the lower the number means longer processing time 
    define("DETAIL", 5); 

    define("DEFAULT_WIDTH", 500); 
    define("DEFAULT_HEIGHT", 100); 
    define("DEFAULT_FOREGROUND", "#FF0000"); 
    define("DEFAULT_BACKGROUND", "#FFFFFF"); 

    /** 
    * GENERAL FUNCTIONS 
    */ 
    function findValues($byte1, $byte2){ 
    $byte1 = hexdec(bin2hex($byte1));       
    $byte2 = hexdec(bin2hex($byte2));       
    return ($byte1 + ($byte2*256)); 
    } 

    /** 
    * Great function slightly modified as posted by Minux at 
    * http://forums.clantemplates.com/showthread.php?t=133805 
    */ 
    function html2rgb($input) { 
    $input=($input[0]=="#")?substr($input, 1,6):substr($input, 0,6); 
    return array(
    hexdec(substr($input, 0, 2)), 
    hexdec(substr($input, 2, 2)), 
    hexdec(substr($input, 4, 2)) 
    ); 
    } 

    if (isset($_FILES["mp3"])) { 

/** 
* PROCESS THE FILE 
*/ 

// temporary file name 
$tmpname = substr(md5(time()), 0, 10); 

// copy from temp upload directory to current 
copy($_FILES["mp3"]["tmp_name"], "{$tmpname}_o.mp3"); 

    // support for stereo waveform? 
$stereo = isset($_POST["stereo"]) && $_POST["stereo"] == "on" ? true : false; 

    // array of wavs that need to be processed 
$wavs_to_process = array(); 

/** 
* convert mp3 to wav using lame decoder 
* First, resample the original mp3 using as mono (-m m), 16 bit (-b 16), and 8 KHz (--resample 8) 
* Secondly, convert that resampled mp3 into a wav 
* We don't necessarily need high quality audio to produce a waveform, doing this process reduces the WAV 
* to it's simplest form and makes processing significantly faster 
*/ 
if ($stereo) { 
     // scale right channel down (a scale of 0 does not work) 
    exec("lame {$tmpname}_o.mp3 --scale-r 0.1 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}_l.wav"); 
     // same as above, left channel 
    exec("lame {$tmpname}_o.mp3 --scale-l 0.1 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}_r.wav"); 
    $wavs_to_process[] = "{$tmpname}_l.wav"; 
    $wavs_to_process[] = "{$tmpname}_r.wav"; 
} else { 
    exec("lame {$tmpname}_o.mp3 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}.wav"); 
    $wavs_to_process[] = "{$tmpname}.wav"; 
} 

// delete temporary files 
unlink("{$tmpname}_o.mp3"); 
unlink("{$tmpname}.mp3"); 

// get user vars from form 
$width = isset($_POST["width"]) ? (int) $_POST["width"] : DEFAULT_WIDTH; 
$height = isset($_POST["height"]) ? (int) $_POST["height"] : DEFAULT_HEIGHT; 
$foreground = isset($_POST["foreground"]) ? $_POST["foreground"] : DEFAULT_FOREGROUND; 
$background = isset($_POST["background"]) ? $_POST["background"] : DEFAULT_BACKGROUND; 
$draw_flat = isset($_POST["flat"]) && $_POST["flat"] == "on" ? true : false; 

$img = false; 

// generate foreground color 
list($r, $g, $b) = html2rgb($foreground); 

// process each wav individually 
for($wav = 1; $wav <= sizeof($wavs_to_process); $wav++) { 

    $filename = $wavs_to_process[$wav - 1]; 

    /** 
    * Below as posted by "zvoneM" on 
    * http://forums.devshed.com/php-development-5/reading-16-bit-wav-file-318740.html 
    * as findValues() defined above 
    * Translated from Croation to English - July 11, 2011 
    */ 
    $handle = fopen($filename, "r"); 
    // wav file header retrieval 
    $heading[] = fread($handle, 4); 
    $heading[] = bin2hex(fread($handle, 4)); 
    $heading[] = fread($handle, 4); 
    $heading[] = fread($handle, 4); 
    $heading[] = bin2hex(fread($handle, 4)); 
    $heading[] = bin2hex(fread($handle, 2)); 
    $heading[] = bin2hex(fread($handle, 2)); 
    $heading[] = bin2hex(fread($handle, 4)); 
    $heading[] = bin2hex(fread($handle, 4)); 
    $heading[] = bin2hex(fread($handle, 2)); 
    $heading[] = bin2hex(fread($handle, 2)); 
    $heading[] = fread($handle, 4); 
    $heading[] = bin2hex(fread($handle, 4)); 

    // wav bitrate 
    $peek = hexdec(substr($heading[10], 0, 2)); 
    $byte = $peek/8; 

    // checking whether a mono or stereo wav 
    $channel = hexdec(substr($heading[6], 0, 2)); 

    $ratio = ($channel == 2 ? 40 : 80); 

    // start putting together the initial canvas 
    // $data_size = (size_of_file - header_bytes_read)/skipped_bytes + 1 
    $data_size = floor((filesize($filename) - 44)/($ratio + $byte) + 1); 
    $data_point = 0; 

    // now that we have the data_size for a single channel (they both will be the same) 
    // we can initialize our image canvas 
    if (!$img) { 
    // create original image width based on amount of detail 
      // each waveform to be processed with be $height high, but will be condensed 
      // and resized later (if specified) 
    $img = imagecreatetruecolor($data_size/DETAIL, $height * sizeof($wavs_to_process)); 

    // fill background of image 
    if ($background == "") { 
     // transparent background specified 
     imagesavealpha($img, true); 
     $transparentColor = imagecolorallocatealpha($img, 0, 0, 0, 127); 
     imagefill($img, 0, 0, $transparentColor); 
    } else { 
     list($br, $bg, $bb) = html2rgb($background); 
     imagefilledrectangle($img, 0, 0, (int) ($data_size/DETAIL), $height * sizeof($wavs_to_process), imagecolorallocate($img, $br, $bg, $bb)); 
    } 
    } 

    while(!feof($handle) && $data_point < $data_size){ 
    if ($data_point++ % DETAIL == 0) { 
     $bytes = array(); 

     // get number of bytes depending on bitrate 
     for ($i = 0; $i < $byte; $i++) 
     $bytes[$i] = fgetc($handle); 

     switch($byte){ 
     // get value for 8-bit wav 
     case 1: 
      $data = findValues($bytes[0], $bytes[1]); 
      break; 
     // get value for 16-bit wav 
     case 2: 
      if(ord($bytes[1]) & 128) 
      $temp = 0; 
      else 
      $temp = 128; 
      $temp = chr((ord($bytes[1]) & 127) + $temp); 
      $data = floor(findValues($bytes[0], $temp)/256); 
      break; 
     } 

     // skip bytes for memory optimization 
     fseek($handle, $ratio, SEEK_CUR); 

     // draw this data point 
     // relative value based on height of image being generated 
     // data values can range between 0 and 255 
     $v = (int) ($data/255 * $height); 

     // don't print flat values on the canvas if not necessary 
     if (!($v/$height == 0.5 && !$draw_flat)) 
     // draw the line on the image using the $v value and centering it vertically on the canvas 
     imageline(
      $img, 
      // x1 
      (int) ($data_point/DETAIL), 
      // y1: height of the image minus $v as a percentage of the height for the wave amplitude 
      $height * $wav - $v, 
      // x2 
      (int) ($data_point/DETAIL), 
      // y2: same as y1, but from the bottom of the image 
      $height * $wav - ($height - $v), 
      imagecolorallocate($img, $r, $g, $b) 
     );   

    } else { 
     // skip this one due to lack of detail 
     fseek($handle, $ratio + $byte, SEEK_CUR); 
    } 
    } 

    // close and cleanup 
    fclose($handle); 

    // delete the processed wav file 
    unlink($filename); 

} 

header("Content-Type: image/png"); 

// want it resized? 
if ($width) { 
    // resample the image to the proportions defined in the form 
    $rimg = imagecreatetruecolor($width, $height); 
    // save alpha from original image 
    imagesavealpha($rimg, true); 
    imagealphablending($rimg, false); 
    // copy to resized 
    imagecopyresampled($rimg, $img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img)); 
    imagepng($rimg); 
    imagedestroy($rimg); 
} else { 
    imagepng($img); 
} 

imagedestroy($img); 

    } else { 

?> 

    <form method="post" action="<?php print $_SERVER["REQUEST_URI"]; ?>"  enctype="multipart/form-data"> 

    <p>MP3 File:<br /> 
    <input type="file" name="mp3" /></p> 

    <p>Image Width:<br /> 
    <input type="text" name="width" value="<?php print DEFAULT_WIDTH; ?>" /></p> 

    <p>Image Height:<br /> 
    <input type="text" name="height" value="<?php print DEFAULT_HEIGHT; ?>" /></p> 

    <p>Foreground Color: <small>(HEX/HTML color code)</small><br /> 
    <input type="text" name="foreground" value="<?php print DEFAULT_FOREGROUND; ?>" /></p> 

    <p>Background Color: (Leave blank for transparent background) <small>(HEX/HTML color code)</small><br /> 
    <input type="text" name="background" value="<?php print DEFAULT_BACKGROUND; ?>" /></p> 

    <p>Draw flat-line? <input type="checkbox" name="flat" /></p> 

    <p>Stereo waveform? <input type="checkbox" name="stereo" /></p> 

    <p><input type="submit" value="Generate Waveform" /></p> 

    </form> 

<?php 

    }  
+0

您的主機是否支持exec()函數? – Stefan

+0

@Stefan我不確定,但看起來似乎不是這樣,通過閱讀http://hostmonsterforums.com/archive/index.php/t-6371.html有什麼我可以取代exec()? Thanx – CosmicRabbitMediaInc

+0

如果你的主機禁用了這個功能,那麼你可以做的不多。你將不得不尋找一個PHP的解決方案,然後不使用外部程序 – Stefan

回答

0

如果因任何原因這個腳本是無法打開的音頻文件中的任何一個,它會失敗併產生一個黑匣子。所以假設主機沒有阻塞exec(),並且根據您的服務器配置,這可能是路徑問題。你可能會想嘗試的一個或兩個以下:

  • 使用完整路徑「跛腳」可執行文件在執行exec()調用
  • 使用的完整路徑的音頻文件,在EXEC( )調用,並在腳本中的其他地方
exec("/usr/local/bin/lame /path/to/{$tmpname}_o.mp3 -m m -S -f -b 16 --resample 8 /path/to/{$tmpname}.mp3 && /usr/local/bin/lame -S --decode /path/to/{$tmpname}.mp3 {$tmpname}.wav"); 
0

我發現好的庫用於正是這樣做的:JustWave Project 上述所有屬實DO ...

  1. 您需要一個可執行庫來在服務器端生成waveimage。此腳本使用FFMEG
  2. 對於緩存,該庫使用SQLite
  3. 您可以在本地生成圖像和文件長度數據,然後上傳,如果您在實際服務器上沒有FFMEG。
  4. 不錯的簡單輸出,包括播放器,顏色可調。

希望這可以幫助有相同需求的人。