File: demo.joinmp3.php

package info (click to toggle)
php-getid3 1.9.12%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,708 kB
  • ctags: 4,710
  • sloc: php: 30,345; makefile: 13
file content (135 lines) | stat: -rw-r--r-- 5,447 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org>               //
//  available at http://getid3.sourceforge.net                 //
//            or http://www.getid3.org                         //
//          also https://github.com/JamesHeinrich/getID3       //
/////////////////////////////////////////////////////////////////
//                                                             //
// /demo/demo.joinmp3.php - part of getID3()                   //
// Sample script for splicing two or more MP3s together into   //
// one file. Does not attempt to fix VBR header frames.        //
// Can also be used to extract portion from single file.       //
// See readme.txt for more details                             //
//                                                            ///
/////////////////////////////////////////////////////////////////


// sample usage:
//   $FilenameOut   = 'combined.mp3';
//   $FilenamesIn[] = 'first.mp3';                    // filename with no start/length parameters
//   $FilenamesIn[] = array('second.mp3',   0,   0);  // filename with zero for start/length is the same as not specified (start = beginning, length = full duration)
//   $FilenamesIn[] = array('third.mp3',    0,  10);  // extract first 10 seconds of audio
//   $FilenamesIn[] = array('fourth.mp3', -10,   0);  // extract last 10 seconds of audio
//   $FilenamesIn[] = array('fifth.mp3',   10,   0);  // extract everything except first 10 seconds of audio
//   $FilenamesIn[] = array('sixth.mp3',    0, -10);  // extract everything except last 10 seconds of audio
//   if (CombineMultipleMP3sTo($FilenameOut, $FilenamesIn)) {
//       echo 'Successfully copied '.implode(' + ', $FilenamesIn).' to '.$FilenameOut;
//   } else {
//       echo 'Failed to copy '.implode(' + ', $FilenamesIn).' to '.$FilenameOut;
//   }
//
// Could also be called like this to extract portion from single file:
//   CombineMultipleMP3sTo('sample.mp3', array(array('input.mp3', 0, 30))); // extract first 30 seconds of audio


function CombineMultipleMP3sTo($FilenameOut, $FilenamesIn) {

	foreach ($FilenamesIn as $nextinputfilename) {
		if (is_array($nextinputfilename)) {
			$nextinputfilename = $nextinputfilename[0];
		}
		if (!is_readable($nextinputfilename)) {
			echo 'Cannot read "'.$nextinputfilename.'"<BR>';
			return false;
		}
	}
	if ((file_exists($FilenameOut) && !is_writeable($FilenameOut)) || (!file_exists($FilenameOut) && !is_writeable(dirname($FilenameOut)))) {
		echo 'Cannot write "'.$FilenameOut.'"<BR>';
		return false;
	}

	require_once(dirname(__FILE__).'/../getid3/getid3.php');
	ob_start();
	if ($fp_output = fopen($FilenameOut, 'wb')) {

		ob_end_clean();
		// Initialize getID3 engine
		$getID3 = new getID3;
		foreach ($FilenamesIn as $nextinputfilename) {
			$startoffset = 0;
			$length_seconds      = 0;
			if (is_array($nextinputfilename)) {
				@list($nextinputfilename, $startoffset, $length_seconds)  = $nextinputfilename;
			}
			$CurrentFileInfo = $getID3->analyze($nextinputfilename);
			if ($CurrentFileInfo['fileformat'] == 'mp3') {

				ob_start();
				if ($fp_source = fopen($nextinputfilename, 'rb')) {

					ob_end_clean();
					$CurrentOutputPosition = ftell($fp_output);

					// copy audio data from first file
					$start_offset_bytes = $CurrentFileInfo['avdataoffset'];
					if ($startoffset > 0) { // start X seconds from start of audio
						$start_offset_bytes = $CurrentFileInfo['avdataoffset'] + round($CurrentFileInfo['bitrate'] / 8 * $startoffset);
					} elseif ($startoffset < 0) { // start X seconds from end of audio
						$start_offset_bytes = $CurrentFileInfo['avdataend'] + round($CurrentFileInfo['bitrate'] / 8 * $startoffset);
					}
					$start_offset_bytes = max($CurrentFileInfo['avdataoffset'], min($CurrentFileInfo['avdataend'], $start_offset_bytes));

					$end_offset_bytes = $CurrentFileInfo['avdataend'];
					if ($length_seconds > 0) { // seconds from start of audio
						$end_offset_bytes = $start_offset_bytes + round($CurrentFileInfo['bitrate'] / 8 * $length_seconds);
					} elseif ($length_seconds < 0) { // seconds from start of audio
						$end_offset_bytes = $CurrentFileInfo['avdataend'] + round($CurrentFileInfo['bitrate'] / 8 * $startoffset);
					}
					$end_offset_bytes = max($CurrentFileInfo['avdataoffset'], min($CurrentFileInfo['avdataend'], $end_offset_bytes));

					if ($end_offset_bytes <= $start_offset_bytes) {
						echo 'failed to copy '.$nextinputfilename.' from '.$startoffset.'-seconds start for '.$length_seconds.'-seconds length (not enough data)';
						fclose($fp_source);
						fclose($fp_output);
						return false;
					}

					fseek($fp_source, $start_offset_bytes, SEEK_SET);
					while (!feof($fp_source) && (ftell($fp_source) < $end_offset_bytes)) {
						fwrite($fp_output, fread($fp_source, min(32768, $end_offset_bytes - ftell($fp_source))));
					}
					fclose($fp_source);

				} else {

					$errormessage = ob_get_contents();
					ob_end_clean();
					echo 'failed to open '.$nextinputfilename.' for reading';
					fclose($fp_output);
					return false;

				}

			} else {

				echo $nextinputfilename.' is not MP3 format';
				fclose($fp_output);
				return false;

			}

		}

	} else {

		$errormessage = ob_get_contents();
		ob_end_clean();
		echo 'failed to open '.$FilenameOut.' for writing';
		return false;

	}

	fclose($fp_output);
	return true;
}