startRecording not working using RecordRTC with RTCMultiConnection - webrtc

I am trying to record every new session/user added to RTCMultiConnection.
i am using the following demo url in application
https://rtcmulticonnection.herokuapp.com/demos/Audio+Video+TextChat+FileSharing.html
Now i have added the following cdn reference to the code.
https://cdn.webrtc-experiment.com/RecordRTC.js
and this is the code i am working with but connection.streams[event.streamid].startRecording(); is not working.
// ..................RTCMultiConnection Code.............
// ......................................................
var connection = new RTCMultiConnection();
var btnStopRec = document.getElementById("btnStopRecording");
connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';
connection.enableFileSharing = true;
connection.session = {
audio: true,
video: true,
data: true,
};
connection.sdpConstraints.mandatory = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true,
};
connection.onstream = function (event)
{
document.body.appendChild(event.mediaElement);
console.log("stream recording starts")
connection.streams[event.streamid].startRecording();
console.log("stream recording started")
}

I included all possible situations in a single snippet, below. Please take only the code that you need:
// global object that contains multiple recorders
var recorders = {};
// auto start recorder as soon as stream starts/begins
connection.onstream = function(event) {
document.body.appendChild(event.mediaElement);
recorders[event.streamid] = RecordRTC(event.stream, {
type: 'video'
});
recorders[event.streamid].startRecording();
};
// auto stop recorder as soon as stream stops/ends
connection.onstreamended = function(event) {
if (recorders[event.streamid]) {
recorders[event.streamid].stopRecording(function() {
var blob = recorders[event.streamid].getBlob();
var url = URL.createObjectURL(blob);
window.open(url);
delete recorders[streamid]; // clear
});
}
if (event.mediaElement.parentNode) {
event.mediaElement.parentNode.removeChild(event.mediaElement);
}
};
// stop single recorder
document.getElementById('manually-stop-single-recording').onclick = function() {
var streamid = prompt('Enter streamid');
recorders[streamid].stopRecording(function() {
var blob = recorders[streamid].getBlob();
var url = URL.createObjectURL(blob);
window.open(url);
delete recorders[streamid]; // clear
});
};
// stop all recorders
document.getElementById('manually-stop-all-recordings').onclick = function() {
Object.keys(recorders).forEach(function(streamid) {
recorders[streamid].stopRecording(function() {
var blob = recorders[streamid].getBlob();
var url = URL.createObjectURL(blob);
window.open(url);
delete recorders[streamid]; // clear
});
});
};
// record outside onstream event
// i.e. start recording anytime manually
document.getElementById('record-stream-outside-the-onstream-event').onclick = function() {
var streamid = prompt('Enter streamid');
var stream = connection.streamEvents[streamid].stream;
recorders[streamid] = RecordRTC(stream, {
type: 'video'
});
recorders[streamid].startRecording();
};

Related

How to pass pdf file to Controller that requires IFormFile

I've been working on this the whole day and did my research already, I can't seem to find a solution anywhere. I have this function that calls a List in my controller, the List needs a IFormFile parameter,
here's my javascript method
function fileUploader_uploaded(e) {
const file = e.file;
const fileReader = new FileReader();
fileReader.onload = function () {
toggleDropZoneActive($("#dropzone-external")[0], false);
$("#dropzone-item")[0].data = fileReader.result;
}
fileReader.readAsDataURL(file);
const _fileReader = new FileReader();
var r = _fileReader.readAsBinaryString(file);
$("#dropzone-text")[0].style.display = "none";
$.ajax({
url: '#Url.Action("_Index", "FileUploader")',
data: { CFile: r}, // I'm trying to pass the pdf file here
cache: false,
success: function (data) {
console.log(data);
}
});
}
and this is my List in controller
public object _Index(IFormFile CFile)
{
if (CFile != null)
{
try
{
string documentText = "";
using PdfDocumentProcessor documentProcessor = new PdfDocumentProcessor();
documentProcessor.LoadDocument(CFile.OpenReadStream());
documentText = documentProcessor.Text;
string word = #"([0-9]+.[0-9]+-[0-9]+)";
Regex regex = new Regex(word);
foreach (Match match in regex.Matches(documentText))
{
sectionsList.Add(match.Value.ToString());
}
}
catch
{
Response.StatusCode = 400;
}
}
else
{
_logger.LogInformation("empty");
}
return sectionsList;
}
the CFile is always empty i tried different ways already like passing
data: { CFile: e.file}
Does anyone else have idea?
From this code data: { CFile: e.file}, you post it as the string, so it can not be recognized as a file. You need to use FormData and change the contentType.
function fileUploader_uploaded(e) {
const file = e.file;
const fileReader = new FileReader();
fileReader.onload = function () {
toggleDropZoneActive($("#dropzone-external")[0], false);
$("#dropzone-item")[0].data = fileReader.result;
}
fileReader.readAsDataURL(file);
const _fileReader = new FileReader();
var r = _fileReader.readAsBinaryString(file);
$("#dropzone-text")[0].style.display = "none";
//----------edit here---------
var form = new FormData()
form.append('CFile', file)
$.ajax({
url: '#Url.Action("_Index", "FileUploader")',
method:'post',
data: form,
cache: false,
contentType: false,
processData: false,
success: function (data) {
}
});
}
The bakend should add [FromForm].
[HttpPost]
public object _Index([FromForm]IFormFile CFile)

RTCMulticonnection initiator no camera

I need some help please if the initiator of the room has no camera,I want the joiner that has both audio and camera to be used. but the problem is that I set to false to video mediacontstraints. now the joiner will only have the audio the camera is gone what I want is audio and video for the joiner.
#Muaz Khan - RTCMultiConnection.js
var initiator = new RTCMultiConnection();
initiator.socketURL = 'url here';
initiator.session = {
audio: true,
video:false,
};
initiator.mediaConstraints = {
audio: true,
video: false
};
initiator.sdpConstraints = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
};
initiator.iceServers = [];
initiator.iceServers.push({
urls: "urls"
});
initiator.iceServers.push({
urls: "urls",
username: "username",
credential: "credential"
});
initiator.audiosContainer = document.getElementById('audios-container');
initiator.onstream = function(event) {
var width = parseInt(initiator.audiosContainer.clientWidth / 4) - 20;
console.log("the dispatcher width is",width);
var mediaElement = getHTMLMediaElement(event.mediaElement, {
title: event.userid,
buttons: ['full-screen'],
width: width,
showOnMouseEnter: false
});
initiator.audiosContainer.appendChild(mediaElement);
setTimeout(function() {
mediaElement.media.play();
}, 5000);
mediaElement.id = event.streamid;
};
initiator.onstreamended = function(event) {
var mediaElement = document.getElementById(event.streamid);
if (mediaElement) {
mediaElement.parentNode.removeChild(mediaElement);
}
};
initiator.openOrJoin('channel-id', function(isRoomExist, roomid) {
if (!isRoomExist) {
}
});
// for participant
var connection = new RTCMultiConnection();
connection.socketURL = 'url here';
connection.session = {
audio: true,
video: true
};
connection.mediaConstraints = {
audio: true,
video: true
};
connection.sdpConstraints.mandatory = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
};
connection.iceServers = [];
connection.iceServers.push({
urls: "urls"
});
connection.iceServers.push({
urls: "urls",
username: "username",
credential: "password"
});
connection.audiosContainer = document.getElementById('audios-container');
connection.onstream = function(event) {
var width = parseInt(connection.audiosContainer.clientWidth / 2) - 20;
console.log("the responder width is",width);
var mediaElement = getHTMLMediaElement(event.mediaElement, {
title: event.userid,
buttons: ['full-screen'],
width: width,
showOnMouseEnter: false
});
connection.audiosContainer.appendChild(mediaElement);
setTimeout(function() {
mediaElement.media.play();
}, 5000);
mediaElement.id = event.streamid;
};
connection.onstreamended = function(event) {
var mediaElement = document.getElementById(event.streamid);
if (mediaElement) {
mediaElement.parentNode.removeChild(mediaElement);
}
};
connection.openOrJoin('channel-id', function(isRoomExist, roomid) {
if (!isRoomExist) {
}
});
Thank you in advance.
Untested, but you should be able to init your RTC connection with a dummy video+audio MediaStream, even if your user doesn't have any device, and without asking them for any approval:
function SilentStream(videoColor) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', {alpha: false});
ctx.fillStyle = videoColor || 'black';
ctx.fillRect(0,0,canvas.width, canvas.height);
const videoStream = canvas.captureStream();
const videoTrack = videoStream.getVideoTracks()[0];
const a_ctx = new (window.AudioContext || window.webkitAudioContext)();
const audioStream = a_ctx.createMediaStreamDestination().stream;
const audioTrack = audioStream.getAudioTracks()[0];
return new MediaStream([videoTrack, audioTrack]);
}
// just to show it's streaming
black.srcObject = SilentStream();
green.srcObject = SilentStream('green');
<video id="black" controls autoplay></video>
<video id="green" controls autoplay></video>

rtcmulticonnection: webrtc recordrtc not returning a blob

I am trying to simply record the webrtc video using what I though was a standard example. The library is here: https://github.com/muaz-khan/RTCMultiConnection
rtcMultiConnection.onstream = function(e) {
var mediaElement = getMediaElement(e.mediaElement, {
onRecordingStarted: function(type) {
// www.RTCMultiConnection.org/docs/startRecording/
rtcMultiConnection.streams[e.streamid].startRecording();
},
onRecordingStopped: function(type) {
// www.RTCMultiConnection.org/docs/stopRecording/
rtcMultiConnection.streams[e.streamid].stopRecording(function(blob){
console.log("test");
console.log(blob);
});
}});}
I can follow the steps through the function calls, the issue is that the callback is never run from recordrtc.js....
It goes to line 100 of https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js
There it runs:
mediaRecorder.stop(_callback);
Which never calls the callback....
Even calling functions directly doesn't work:
console.log(rtcMultiConnection.streams[e.streamid].audioRecorder.getBlob());
console.log(rtcMultiConnection.streams[e.streamid].videoRecorder.save("a.png"));
I am wondering if two different versions of recordrtc and rtcmulticonneciton are interacting.... Any ideas? Maybe an older recordrtc, but I can't find an older version
Please use blob.video:
var stream = connection.streams['stream-id'];
stream.stopRecording(function(blob) {
var h2;
if (blob.audio) {
h2 = document.createElement('h2');
h2.innerHTML = 'Open recorded ' + blob.audio.type + '';
div.appendChild(h2);
}
if (blob.video) {
h2 = document.createElement('h2');
h2.innerHTML = 'Open recorded ' + blob.video.type + '';
div.appendChild(h2);
}
});
Updated at March 29, 2016
Here is the actual documentation:
http://www.rtcmulticonnection.org/docs/startRecording/
Please make sure that:
You are using v2.2.2
You called startRecording first
For v3, you can directly use the RecordRTC:
connection.onstream = function(event) {
recordStream(event.stream);
};
function recordStream(stream) {
if (!!window.recorder) return;
window.recorder = RecordRTC(stream, {
type: 'video'
});
recorder.startRecording();
}
btnStopRecording.onclick = function() {
if (!window.recorder) return;
recorder.stopRecording(function() {
var blob = recorder.blob;
// or dataURL
recorder.getDataURL(func_callback);
});
};
btnStartRecording.onclick = function() {
var stream = connection.attachStreams[0];
recordStream(straem);
// or
var stream = connection.streamEvents['stream-id'].stream;
recordStream(straem);
};
Above snippet can be used within v2.2.2 as well.

Google Places API - Getting Phone Number and Website

I believe I need to make follow up calls to get the results I am looking for. However, I cannot get the phone number and www url for any of the results I pull up.
I am a novice and need some help explaining where in this code I can get the correct results pulled. Please see the demo site here:
http://news.yeselectric.com/gmaps-excel-master/
Here is my JS code:
var store = (function () {
var searchBox,
infowindow,
markers = [],
myLatlng = new google.maps.LatLng(50.0019, 10.1419),
myOptions = { zoom: 6, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: false, streetViewControl:false },
customIcons = { iconblue: './icons/blue.png' };
var init = function() {
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
input = (document.getElementById('pac-input'));
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
searchBox = new google.maps.places.SearchBox((input));
store.listener();
},
listener = function() {
google.maps.event.addListener(searchBox, 'places_changed', function() {
//search for places
var places = searchBox.getPlaces();
for (var i = 0, marker; marker = markers[i]; i++) {
marker.setMap(null);
}
//set markers zero
markers = [];
$('.addaddress').empty();
//get new bounds
var bounds = new google.maps.LatLngBounds();
for (var i = 0, place; place = places[i]; i++) {
store.create_marker(place);
//append to the table
$('.addaddress').append('<tr><td>'+ place.name +'</td><td>'+ place.formatted_address +'</td><td>'+ place.formatted_phone_number +'</td><td>'+ place.website +'</td></tr>');
bounds.extend(place.geometry.location);
}
//set the map
map.fitBounds(bounds);
});
},
create_marker = function(info) {
//create a marker for each place
var marker = new google.maps.Marker({ map: map, icon: customIcons.iconblue, title: info.name, position: info.geometry.location });
//infowindow setup
google.maps.event.addListener(marker, "click", function() {
if (infowindow) {
infowindow.close();
}
infowindow = new google.maps.InfoWindow({content: info.name});
infowindow.open(map, marker);
});
//push the marker
markers.push(marker);
}
return {
init: init,
listener: listener,
create_marker: create_marker
};
})();
google.maps.event.addDomListener(window, 'load', store.init);
Google's API returns different place metadata, depending on which call you're using. To get more place details, you'll need to get the place's placeId and use that to make a call to place.getDetails()
Here's a more thorough answer: https://stackoverflow.com/a/9523345/2141296

Deferring a Dojo Deferred

I'm having a bit of a problem getting a deferred returned from a method in a widget. The method is itself returns a Deferred as it's an xhrPost. The code is as such (using dojo 1.8)
Calling Code:
quorum = registry.byId("quorumPanel");
var deferredResponse = quorum.updateSelectionCount();
deferredResponse.then(function(data){
console.log("Success: ", data);
}, function(err){
console.log("Error: ", err);
});
and the code in the widget:
updateSelectionCount: function() {
var self = this;
var deferredResponse = xhr.post({
url: "ajxclwrp.php",
content: [arguments here],
handleAs: "json"});
deferredResponse.then(function(response) {
var anotherDeferred = new Deferred();
var _boolA = true;
var _boolB = true;
dojo.forEach(response.result, function(relationshipInfo){
[do a bunch of stuff here too set _boolA and/or _boolB]
});
self._sethasRequiredAttr(_hasRequired);
self._setHasRequestedAttr(_hasRequested);
self.quorumInfo.innerHTML = quorumHtml;
// Below is not working
anotherDeferred.resolve('foo');
return anotherDeferred;
});
}
Do I need to set up another promise and use promise/all. Im confused/frustrated at this point.
TIA.
the .then() method returns another deferred. You just need to put a return statement in.
updateSelectionCount: function() {
var self = this;
var deferredResponse = xhr.post({
url: "ajxclwrp.php",
content: [arguments here],
handleAs: "json"});
return deferredResponse.then(function(response) {
var _boolA = true;
var _boolB = true;
dojo.forEach(response.result, function(relationshipInfo){
[do a bunch of stuff here too set _boolA and/or _boolB]
});
self._sethasRequiredAttr(_hasRequired);
self._setHasRequestedAttr(_hasRequested);
self.quorumInfo.innerHTML = quorumHtml;
return "foo";
});
}