Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RecordRTC/PHP/FFmpeg synced audio/video recording demo added.
This demo can record both audio/video; and merge both files in single WebM container. Both audio video are synced using ffmpeg commands! You can record longest possible audio/video files. At least, minimum 5 minutes recording is tested! issues? 1. Browser hangs for at least 30 seconds for encoding large video webp array into WebM. 2. Video is not 100% smooth....though it is at least 98% stable! One thing you MUST NEVER forget; you MUST be using latest ffmpeg installation; at least the one which supports "libvpx" and "libvorbis".
- Loading branch information
Showing
5 changed files
with
332 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
php_value session.gc_maxlifetime 10800 | ||
php_value max_input_time 10800 | ||
php_value max_execution_time 10800 | ||
php_value upload_max_filesize 500M | ||
php_value post_max_size 500M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
<!-- | ||
// Muaz Khan - www.MuazKhan.com | ||
// MIT License - www.WebRTC-Experiment.com/licence | ||
// Documentation - github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC | ||
--> | ||
|
||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>RecordRTC / PHP / FFmpeg</title> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | ||
<link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan"> | ||
<meta name="author" content="Muaz Khan"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | ||
|
||
<style> | ||
body, html { | ||
background: black; | ||
color: white; | ||
text-align: center; | ||
} | ||
|
||
button, a { | ||
background: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(0%, #fff), color-stop(100%, #eaeaea)); | ||
background: -webkit-linear-gradient(top, #fff, #eaeaea); | ||
background: -moz-linear-gradient(top, #fff, #eaeaea); | ||
background: -o-linear-gradient(top, #fff, #eaeaea); | ||
background: linear-gradient(top, #fff, #eaeaea); | ||
border: 1px solid white; | ||
border-radius: 5px; | ||
color: #4f4f4f; | ||
padding: 8px 15px; | ||
text-decoration: none; | ||
text-transform: capitalize; | ||
} | ||
|
||
button:hover, a:hover, button:active, a:active, button:focus, a:focus { | ||
-moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5); | ||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5); | ||
background: #303030; | ||
border-color: white; | ||
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5); | ||
color: white; | ||
} | ||
|
||
button[disabled] { | ||
background: transparent; | ||
border-color: rgb(83, 81, 81); | ||
color: rgb(139, 133, 133); | ||
} | ||
</style> | ||
|
||
<!-- script used for audio/video/gif recording --> | ||
<script src="//www.webrtc-experiment.com/RecordRTC.js"> </script> | ||
</head> | ||
|
||
<body style="text-align: center;"> | ||
<h1> | ||
<a href="https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC">RecordRTC</a> | ||
<a href="https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC-to-PHP">PHP</a> | ||
<a href="https://github.com/muaz-khan/WebRTC-Experiment/tree/master/ffmpeg">FFmpeg</a> | ||
</h1> | ||
<section class="experiment"> | ||
<p style="text-align: center;"> | ||
<video id="preview" controls style="border: 1px solid rgb(15, 158, 238); height: 240px; max-width: 100%; vertical-align: top; width: 320px;"></video> | ||
</p> | ||
|
||
<button id="record">Record</button> | ||
<button id="stop" disabled>Stop</button> | ||
|
||
<div id="container" style="padding: 1em 2em;"></div> | ||
</section> | ||
|
||
<script> | ||
function PostBlob(audioBlob, videoBlob, fileName) { | ||
var formData = new FormData(); | ||
formData.append('filename', fileName); | ||
formData.append('audio-blob', audioBlob); | ||
formData.append('video-blob', videoBlob); | ||
xhr('save.php', formData, function(ffmpeg_output) { | ||
document.querySelector('h1').innerHTML = ffmpeg_output.replace( /\\n/g , '<br />'); | ||
preview.src = 'uploads/' + fileName + '-merged.webm'; | ||
preview.play(); | ||
preview.muted = false; | ||
}); | ||
} | ||
|
||
var record = document.getElementById('record'); | ||
var stop = document.getElementById('stop'); | ||
|
||
var audio = document.querySelector('audio'); | ||
|
||
var recordVideo = document.getElementById('record-video'); | ||
var preview = document.getElementById('preview'); | ||
|
||
var container = document.getElementById('container'); | ||
|
||
var isFirefox = !!navigator.mozGetUserMedia; | ||
|
||
var recordAudio, recordVideo; | ||
record.onclick = function() { | ||
record.disabled = true; | ||
!window.stream && navigator.getUserMedia({ | ||
audio: true, | ||
video: true | ||
}, function(stream) { | ||
window.stream = stream; | ||
onstream(); | ||
}, function(error) { | ||
alert(JSON.stringify(error, null, '\t')); | ||
}); | ||
|
||
window.stream && onstream(); | ||
|
||
function onstream() { | ||
preview.src = window.URL.createObjectURL(stream); | ||
preview.play(); | ||
preview.muted = true; | ||
|
||
recordAudio = RecordRTC(stream, { | ||
bufferSize: 16384 | ||
}); | ||
recordAudio.startRecording(); | ||
|
||
if (!isFirefox) { | ||
recordVideo = RecordRTC(stream, { | ||
type: 'video' | ||
}); | ||
recordVideo.startRecording(); | ||
} | ||
|
||
stop.disabled = false; | ||
} | ||
}; | ||
|
||
var fileName; | ||
stop.onclick = function() { | ||
document.querySelector('h1').innerHTML = 'Getting Blobs...'; | ||
|
||
record.disabled = false; | ||
stop.disabled = true; | ||
|
||
preview.src = ''; | ||
preview.poster = 'ajax-loader.gif'; | ||
|
||
fileName = Math.round(Math.random() * 99999999) + 99999999; | ||
|
||
if (!isFirefox) { | ||
recordAudio.stopRecording(function() { | ||
document.querySelector('h1').innerHTML = 'Got audio-blob. Getting video-blob...'; | ||
recordVideo.stopRecording(function() { | ||
document.querySelector('h1').innerHTML = 'Uploading to server...'; | ||
PostBlob(recordAudio.getBlob(), recordVideo.getBlob(), fileName); | ||
}); | ||
}); | ||
} | ||
}; | ||
|
||
function xhr(url, data, callback) { | ||
var request = new XMLHttpRequest(); | ||
request.onreadystatechange = function() { | ||
if (request.readyState == 4 && request.status == 200) { | ||
callback(request.responseText); | ||
} | ||
}; | ||
request.open('POST', url); | ||
request.send(data); | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<?php | ||
// Muaz Khan - www.MuazKhan.com | ||
// MIT License - www.WebRTC-Experiment.com/licence | ||
// Documentation - github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC | ||
|
||
// make sure that you're using newest ffmpeg version! | ||
|
||
// because we've different ffmpeg commands for windows & linux | ||
// that's why following script is used to fetch target OS | ||
$OSList = array | ||
( | ||
'Windows 3.11' => 'Win16', | ||
'Windows 95' => '(Windows 95)|(Win95)|(Windows_95)', | ||
'Windows 98' => '(Windows 98)|(Win98)', | ||
'Windows 2000' => '(Windows NT 5.0)|(Windows 2000)', | ||
'Windows XP' => '(Windows NT 5.1)|(Windows XP)', | ||
'Windows Server 2003' => '(Windows NT 5.2)', | ||
'Windows Vista' => '(Windows NT 6.0)', | ||
'Windows 7' => '(Windows NT 7.0)', | ||
'Windows NT 4.0' => '(Windows NT 4.0)|(WinNT4.0)|(WinNT)|(Windows NT)', | ||
'Windows ME' => 'Windows ME', | ||
'Open BSD' => 'OpenBSD', | ||
'Sun OS' => 'SunOS', | ||
'Linux' => '(Linux)|(X11)', | ||
'Mac OS' => '(Mac_PowerPC)|(Macintosh)', | ||
'QNX' => 'QNX', | ||
'BeOS' => 'BeOS', | ||
'OS/2' => 'OS/2', | ||
'Search Bot'=>'(nuhk)|(Googlebot)|(Yammybot)|(Openbot)|(Slurp)|(MSNBot)|(Ask Jeeves/Teoma)|(ia_archiver)' | ||
); | ||
// Loop through the array of user agents and matching operating systems | ||
foreach($OSList as $CurrOS=>$Match) | ||
{ | ||
// Find a match | ||
if (eregi($Match, $_SERVER['HTTP_USER_AGENT'])) | ||
{ | ||
// We found the correct match | ||
break; | ||
} | ||
} | ||
|
||
// if it is audio-blob | ||
if (isset($_FILES["audio-blob"])) { | ||
$uploadDirectory = 'uploads/'.$_POST["filename"].'.wav'; | ||
if (!move_uploaded_file($_FILES["audio-blob"]["tmp_name"], $uploadDirectory)) { | ||
echo("Problem writing audio file to disk!"); | ||
} | ||
else { | ||
// if it is video-blob | ||
if (isset($_FILES["video-blob"])) { | ||
$uploadDirectory = 'uploads/'.$_POST["filename"].'.webm'; | ||
if (!move_uploaded_file($_FILES["video-blob"]["tmp_name"], $uploadDirectory)) { | ||
echo("Problem writing video file to disk!"); | ||
} | ||
else { | ||
$audioFile = 'uploads/'.$_POST["filename"].'.wav'; | ||
$videoFile = 'uploads/'.$_POST["filename"].'.webm'; | ||
|
||
$mergedFile = 'uploads/'.$_POST["filename"].'-merged.webm'; | ||
|
||
// ffmpeg depends on yasm | ||
// libvpx depends on libvorbis | ||
// libvorbis depends on libogg | ||
// make sure that you're using newest ffmpeg version! | ||
|
||
if(!strrpos($CurrOS, "Windows")) { | ||
$cmd = '-i '.$audioFile.' -itsoffset -00:00:02 -i '.$videoFile.' -map 0:0 -map 1:0 '.$mergedFile; | ||
} | ||
else { | ||
$cmd = ' -i '.$audioFile.' -itsoffset -00:00:02 -i '.$videoFile.' -c:v mpeg4 -c:a vorbis -b:v 64k -b:a 12k -strict experimental '.$mergedFile; | ||
} | ||
|
||
exec('ffmpeg '.$cmd.' 2>&1', $out, $ret); | ||
if ($ret){ | ||
echo "There was a problem!\n"; | ||
print_r($cmd.'\n'); | ||
print_r($out); | ||
} else { | ||
echo "Ffmpeg successfully merged audi/video files into single WebM container!\n"; | ||
|
||
unlink($audioFile); | ||
unlink($videoFile); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters