1<?php 2///////////////////////////////////////////////////////////////// 3/// getID3() by James Heinrich <info@getid3.org> // 4// available at https://github.com/JamesHeinrich/getID3 // 5// or https://www.getid3.org // 6// or http://getid3.sourceforge.net // 7// // 8// /demo/demo.joinmp3.php - part of getID3() // 9// Sample script for splicing two or more MP3s together into // 10// one file. Does not attempt to fix VBR header frames. // 11// Can also be used to extract portion from single file. // 12// see readme.txt for more details // 13// /// 14///////////////////////////////////////////////////////////////// 15 16 17// sample usage: 18// $FilenameOut = 'combined.mp3'; 19// $FilenamesIn[] = 'first.mp3'; // filename with no start/length parameters 20// $FilenamesIn[] = array('second.mp3', 0, 0); // filename with zero for start/length is the same as not specified (start = beginning, length = full duration) 21// $FilenamesIn[] = array('third.mp3', 0, 10); // extract first 10 seconds of audio 22// $FilenamesIn[] = array('fourth.mp3', -10, 0); // extract last 10 seconds of audio 23// $FilenamesIn[] = array('fifth.mp3', 10, 0); // extract everything except first 10 seconds of audio 24// $FilenamesIn[] = array('sixth.mp3', 0, -10); // extract everything except last 10 seconds of audio 25// if (CombineMultipleMP3sTo($FilenameOut, $FilenamesIn)) { 26// echo 'Successfully copied '.implode(' + ', $FilenamesIn).' to '.$FilenameOut; 27// } else { 28// echo 'Failed to copy '.implode(' + ', $FilenamesIn).' to '.$FilenameOut; 29// } 30// 31// Could also be called like this to extract portion from single file: 32// CombineMultipleMP3sTo('sample.mp3', array(array('input.mp3', 0, 30))); // extract first 30 seconds of audio 33 34 35function CombineMultipleMP3sTo($FilenameOut, $FilenamesIn) { 36 37 foreach ($FilenamesIn as $nextinputfilename) { 38 if (is_array($nextinputfilename)) { 39 $nextinputfilename = $nextinputfilename[0]; 40 } 41 if (!is_readable($nextinputfilename)) { 42 echo 'Cannot read "'.$nextinputfilename.'"<BR>'; 43 return false; 44 } 45 } 46 if ((file_exists($FilenameOut) && !is_writeable($FilenameOut)) || (!file_exists($FilenameOut) && !is_writeable(dirname($FilenameOut)))) { 47 echo 'Cannot write "'.$FilenameOut.'"<BR>'; 48 return false; 49 } 50 51 require_once(dirname(__FILE__).'/../getid3/getid3.php'); 52 ob_start(); 53 if ($fp_output = fopen($FilenameOut, 'wb')) { 54 55 ob_end_clean(); 56 // Initialize getID3 engine 57 $getID3 = new getID3; 58 foreach ($FilenamesIn as $nextinputfilename) { 59 $startoffset = 0; 60 $length_seconds = 0; 61 if (is_array($nextinputfilename)) { 62 @list($nextinputfilename, $startoffset, $length_seconds) = $nextinputfilename; 63 } 64 $CurrentFileInfo = $getID3->analyze($nextinputfilename); 65 if ($CurrentFileInfo['fileformat'] == 'mp3') { 66 67 ob_start(); 68 if ($fp_source = fopen($nextinputfilename, 'rb')) { 69 70 ob_end_clean(); 71 $CurrentOutputPosition = ftell($fp_output); 72 73 // copy audio data from first file 74 $start_offset_bytes = $CurrentFileInfo['avdataoffset']; 75 if ($startoffset > 0) { // start X seconds from start of audio 76 $start_offset_bytes = $CurrentFileInfo['avdataoffset'] + round(($CurrentFileInfo['bitrate'] / 8) * $startoffset); 77 } elseif ($startoffset < 0) { // start X seconds from end of audio 78 $start_offset_bytes = $CurrentFileInfo['avdataend'] + round(($CurrentFileInfo['bitrate'] / 8) * $startoffset); 79 } 80 $start_offset_bytes = max($CurrentFileInfo['avdataoffset'], min($CurrentFileInfo['avdataend'], $start_offset_bytes)); 81 82 $end_offset_bytes = $CurrentFileInfo['avdataend']; 83 if ($length_seconds > 0) { // set end offset to X seconds from start of audio 84 $end_offset_bytes = $start_offset_bytes + round(($CurrentFileInfo['bitrate'] / 8) * $length_seconds); 85 } elseif ($length_seconds < 0) { // set end offset to X seconds from end of audio 86 $end_offset_bytes = $CurrentFileInfo['avdataend'] + round(($CurrentFileInfo['bitrate'] / 8) * $length_seconds); 87 } 88 $end_offset_bytes = max($CurrentFileInfo['avdataoffset'], min($CurrentFileInfo['avdataend'], $end_offset_bytes)); 89 90 if ($end_offset_bytes <= $start_offset_bytes) { 91 echo 'failed to copy '.$nextinputfilename.' from '.$startoffset.'-seconds start for '.$length_seconds.'-seconds length (not enough data)'; 92 fclose($fp_source); 93 fclose($fp_output); 94 return false; 95 } 96 97 fseek($fp_source, $start_offset_bytes, SEEK_SET); 98 while (!feof($fp_source) && (ftell($fp_source) < $end_offset_bytes)) { 99 fwrite($fp_output, fread($fp_source, min(32768, $end_offset_bytes - ftell($fp_source)))); 100 } 101 fclose($fp_source); 102 103 } else { 104 105 $errormessage = ob_get_contents(); 106 ob_end_clean(); 107 echo 'failed to open '.$nextinputfilename.' for reading'; 108 fclose($fp_output); 109 return false; 110 111 } 112 113 } else { 114 115 echo $nextinputfilename.' is not MP3 format'; 116 fclose($fp_output); 117 return false; 118 119 } 120 121 } 122 123 } else { 124 125 $errormessage = ob_get_contents(); 126 ob_end_clean(); 127 echo 'failed to open '.$FilenameOut.' for writing'; 128 return false; 129 130 } 131 132 fclose($fp_output); 133 return true; 134} 135