How to DRM Content in chromecast - chromecast

we are trying to play drm MPD content from Chrome to Chromecast
Our receiver app code is as follow:
const context = cast.framework.CastReceiverContext.getInstance();
const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.licenseUrl = 'http://widevine/yourLicenseServer';
playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
playbackConfig.licenseRequestHandler = requestInfo => {
requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});
// Update playback config licenseUrl according to provided value in load request.
context.getPlayerManager().setMediaPlaybackInfoHandler((loadRequest, playbackConfig) => {
if (loadRequest.media.customData && loadRequest.media.customData.licenseUrl) {
playbackConfig.licenseUrl = loadRequest.media.customData.licenseUrl;
}
return playbackConfig;
});
I don't get a correct way to pass custom data for drm in the client application.
please help.

I think you are asking how you send the license URL from the sender client (the device 'casing') to the receiver (the device which will receive the request to cast and which actually get and plays the stream) in the custom data.
The custom data is a JSON object and you just need to put the license url into it.
There are two common ways of passing this custom data:
include it in the MediaInfo object using the MediaInfo.Builder.setCustomData method
include it the MediaLoadOptions data
As an example, looking at a MediaInfo example form the Google documents and adding in custom data:
List tracks = new ArrayList();
tracks.add(englishSubtitle);
tracks.add(frenchSubtitle);
tracks.add(frenchAudio);
MediaInfo mediaInfo = MediaInfo.Builder(url)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType(getContentType())
.setMetadata(getMetadata())
.setMediaTracks(tracks)
.setCustomData(yourCustomData) <--- This is the custom data
.build();
'yourCustomData' above is a JSON object which you create and add your data to, in your case your license server URL:
JSONObject yourCustomData = new JSONObject();
try {
yourCustomeData.put("licenseURL", "HTTPS://yourlicenseServerUrl.com");
} catch (JSONException e) {
// Add any error code you want here
e.printStackTrace();
}

please follow the code for js
new ChromecastJS().cast({
content: "xxxxxx",
contentType: "application/dash+xml",
poster: "xxxxxxx",
title: "xxxxx",
description: "xxxxx",
duration: "xxxx",
volume: 0.5,
muted: false,
paused: false,
time: "Xxxxx",
customData: {
drmHeaders: {
customdata: "xxxxxx",
},
drmLaUrl: "xxxx",
drmKsName: "com.widevine.alpha",
},
});

Related

Cant Record Stream Using MediaRecorder In Server?

First I am trying to make a Webrtc peer connection from the browser to the server using SFU model.
Here is the post request which makes the webrtc peer connection from the browser to the server(SFU)
app.post("/broadcast", async ({ body }, res) => {
const peer = new webrtc.RTCPeerConnection({
iceServers: [
{
urls: "stun:stun.stunprotocol.org",
},
],
});
peer.ontrack = (e) => handleTrackEvent(e, peer); <-- Important
const desc = new webrtc.RTCSessionDescription(body.sdp);
await peer.setRemoteDescription(desc);
const answer = await peer.createAnswer();
await peer.setLocalDescription(answer);
const payload = {
sdp: peer.localDescription,
};
res.json(payload);
});
In the handleTrackEvent function, I am getting the stream which I want to start record and save in the server's local storage.
function handleTrackEvent(e, peer) {
console.log(e.streams);
senderStream = e.streams[0];
var recorder = new MediaStreamRecorder(e.streams);
recorder.recorderType = MediaRecorderWrapper;
recorder.mimeType = "video/webm";
recorder.ondataavailable = (blob) => {
console.log(blob);
};
recorder.start(5 * 1000); <-- Error generator
}
But when try to start the recording and get the blob in 5 sec intervals, it gives me "MediaRecorder Not Found" ...
Passing following params over MediaRecorder API. { mimeType: 'video/webm' }
/Users/tecbackup/webrtc-peer/node_modules/msr/MediaStreamRecorder.js:672
mediaRecorder = new MediaRecorder(mediaStream);
^
ReferenceError: MediaRecorder is not defined
I am very new to webrtc, I need some suggestion to save the live stream from the browser to the server....In future, if find the blob, then I will save the blobs sequentially in a mp4 file in the server. Then, on runtime i start pressing ffmpeg in that mp4 file to get 240p, 360p, 720p ts files for hls streaming

handleMessageError when registering Teams connector

I'm developing a Microsoft Teams custom app that can add connectors to Teams channels.
My connector has been working fine for a few months now, but a few weeks ago, the ability to register new connectors has stopped working:
After clicking “Save” on the connector configuration page, “loading” shows up until it times out (see the console screenshot below).
When I look in the browser console, I see that the outbound request was actually successful and notifySuccess() was called on the save event, but Teams does not register it (see full JS code below).
Also, a handleMessageError message is emitted, but I could not figure out what the issue is.
I tried this in the native app and in Chrome, and a client tried it in another instance of Teams as well.
Is this a bug or a (undocumented?) change in the Teams API?
Console / UI screenshot
JSON Error Message:
{
"seq": 1615787354693,
"timestamp": 1615793440583,
"flightSettings": {
"Name": "ConnectorFrontEndSettings",
"AriaSDKToken": "d127f72a3abd41c9b9dd94faca947689-d58285e6-3a68-4cab-a458-37b9d9761d35-7033",
"SPAEnabled": true,
"ClassificationFilterEnabled": true,
"ClientRoutingEnabled": true,
"EnableYammerGroupOption": true,
"EnableFadeMessage": false,
"EnableDomainBasedOwaConnectorList": false,
"EnableDomainBasedTeamsConnectorList": false,
"DevPortalSPAEnabled": true,
"ShowHomeNavigationButtonOnConfigurationPage": false,
"DisableConnectToO365InlineDeleteFeedbackPage": true
},
"status": 500,
"clientType": "SkypeSpaces",
"connectorType": "fc0ee140-b62a-4947-9af1-d19a66a00af8",
"name": "handleMessageError"
}
JS code that runs on the connector's configuration page:
const XHR = new XMLHttpRequest();
const subscriptionApiUrl = "https://XYZ.execute-api.us-east-1.amazonaws.com/Prod/subscriptions/";
const channelsApiBaseURL = "https://www.example.com/api/library/v2/channels/";
const defaultChannelParameters = "sorting=latest&language=en&excludeReviews=true";
const url = new URL(window.location.href);
const clientId = url.searchParams.get("clientid");
const clientSecret = url.searchParams.get("clientsecret");
const teamsSettings = {
entityId: "Example",
contentUrl: "https://www.example.com/xyz",
configName: "Example"
};
var saveEvent;
console.log("Example Connector initializing");
microsoftTeams.initialize();
microsoftTeams.settings.setValidityState(true); // make Save button enabled
microsoftTeams.settings.registerOnSaveHandler(handleSaveEvent);
function handleSaveEvent(e) {
saveEvent = e;
microsoftTeams.settings.setSettings(teamsSettings);
microsoftTeams.settings.getSettings(storeSettings);
}
function storeSettings(settings) {
XHR.addEventListener("load", reportSuccess);
XHR.addEventListener("error", reportFailure);
XHR.open("POST", subscriptionApiUrl);
XHR.setRequestHeader("Content-Type", "application/json");
XHR.send(composePayload(settings.webhookUrl));
console.log("Request to store Example Connector sent");
}
function composePayload(webhookUrl) {
return JSON.stringify({
webhookUrl: webhookUrl,
gaChannelUrl: channelsApiBaseURL + document.getElementById("ga-channel-id").value + "/items?" + defaultChannelParameters,
gaClientId: clientId,
gaClientSecret: clientSecret,
cronSchedule: "0 " + document.getElementById("time").value + " * * " + document.getElementById("frequency"),
postNow: document.getElementById("post-now").checked ? true : false
});
}
function reportSuccess(e) {
console.log("Example Connector registered!");
saveEvent.notifySuccess();
}
function reportFailure(e) {
let msg = "Could not connect to subscription API.";
console.log(msg);
saveEvent.notifyFailure(msg);
}
I got the same error. I registered the connector and downloaded the generated manifest.json then packaged (with icons) and tried to sideload the zip. I got the same error when trying to "Save".
I then tried to edit the generated manifest using the App Studio (App Studio -> Import an existing app) and this time I got a meaningful error saying the property needsIdentity is not valid according the schema from the manifest (https://developer.microsoft.com/en-us/json-schemas/teams/v1.3/MicrosoftTeams.schema.json)
Removing this property fixed the issue and I was able to save the connector configuration.
I could not find any documentation about this property. I checked the last version of the schema by now (1.8) and it's not there !!
I created an issue : https://github.com/MicrosoftDocs/msteams-docs/issues/2949

NativeScript Vue send request with form data (multipart/form-data)

I have a case in my application where I need to send data as form data to a server. The data includes a message and an optional list of files. The problem I'm facing is that when sending the request it's not being formed properly.
Request Payload
Expected (sample with the same request in the browser)
Actual (resulting request when running in NativeScript)
The actual result is that the payload is somehow being URL encoded.
Code example
sendData({ id, message, files }) {
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
const payload = new FormData();
payload.append('message', message);
if (files && files.length > 0) {
files.forEach((file) => {
payload.append(`files`, file, file.name);
});
}
return AXIOS_INSTANCE.post(
`/api/save/${id}`,
payload,
config
);
}
As you can see from the above, I'm using axios and also I'm trying to use FormData to format the data. From my research it seems that NativeScript used to not support binary data via XHR - however looking at this merge request on GitHub it looks like it's been fixed about a year ago.
So my suspicion is that I'm doing something wrong, maybe there's an alternative to using FormData, or else I shouldn't use axios for this particular request?
Version Numbers
nativescript 6.8.0
tns-android 6.5.3
tns-ios 6.5.3
Nativescript's background-http supports multipart form data.
See below for how its configured to do multipart upload
var bghttp = require("nativescript-background-http");
var session = bghttp.session("image-upload");
var request = {
url: url,
method: "POST",
headers: {
"Content-Type": "application/octet-stream"
},
description: "Uploading "
};
var params = [
{ name: "test", value: "value" },
{ name: "fileToUpload", filename: file, mimeType: "image/jpeg" }
];
var task = session.multipartUpload(params, request);

Read Custom request Header in OWIN Authentication

I am trying to provide extra/custom authentication to MS Bot-framework project using OWIN other than default authentication from MS using app id/pwd. Yes the Bot is in-fact an api i tagged Webapi too. I added OWIN startup class and provided middleware to perform OAUTH-2 implementation to validate JWT.
As MS Bot directline calls have a default Bearer token to be passed as Authorization header key,i given custom provider to accept JWT from Bot state. Please note my bot is surfaced in a Web app which will generate a auth token which will be setted in Bot state against unique user id, so i am in need of this user id value to retrieve the token from Bot state. So the best possible way i can think of is to intercept all ajax calls from my Webchat Bot control to add a custom header as "x-user-id", which i will read from my owin middleware request header.
But it was not succeeding as i am not getting the header value in OWIN, which i am passing in ajax calls. But when i checked in Chrome, this header is being sent. I am confused on what could be the issue.
Ajax Interceptor
if (window.XMLHttpRequest && !(window.ActiveXObject)) {
(function (send) {
XMLHttpRequest.prototype.send = function (data) {
this.setRequestHeader('x-user-id', '123456789');
send.call(this, data);
};
})(XMLHttpRequest.prototype.send);
}
AppBuilder Configuration
public void Configuration(IAppBuilder app)
{
var policy = new CorsPolicy()
{
AllowAnyHeader = true,
AllowAnyMethod = true,
AllowAnyOrigin = true,
SupportsCredentials = true
};
policy.ExposedHeaders.Add("x-user-id");
app.UseCors(new CorsOptions()
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(policy)
}
});
app.Map("/api", ctx =>
{
ctx.UseEsoAccessTokenValidation(new EsoAccessTokenOptions
{
AccessTokenKey = "AccessToken",
ChannelId = "webchat",
Scopes = new string[] { "read", "write" }
});
ctx.UseWebApi(WebApiConfig.Register());
});
}
Code to Read Header:
private static async Task<string> GetAccessToken(OAuthRequestTokenContext context, EsoAccessTokenOptions options)
{
string accesstoken = string.Empty;
var request = context.Request;
if (request.Headers.ContainsKey("x-user-id"))
{
userid = request.Headers.Get("x-user-id");
}
}
Chrome Network Screenshot
Please help me understand what i am doing wrong here?
Need to realize that, the requests always pass through the corresponding channels (connectors) and not everything that you add as part of headers will be passed to your bot. Hence we need to pass such data only through supported mechanisms. as Eric mentioned, once such way is leveraging channelData. Anything that you add as part of channelData will pass thru the channel and reach the bot. Hence recommend you to try the same.
Example 1:
{
"type": "conversationUpdate",
"membersAdded": [],
"from": {
"id": "test",
"name": "test"
},
"serviceUrl": "https://directline.botframework.com",
"channelData":{ "userId": "test"}
}
Example 2:
{
"type": "message",
"text": "whats your name",
"from": {
"id": "user1",
"name": "user1"
},
"channelData": {
"userId": "test1234"
}
}`
Hope this helps.
I think the Direct Line strips headers as it translates and transfers messages to your bot. However, you could intercept all messages (like you've done already) and add the x-user-id as custom channel data to each message. Here is an example of custom channel data: https://blog.botframework.com/2017/03/28/Custom-Channel-Data#c-implementation

How can I read a local file in Cloud Code as a string?

I'm using Parse Cloud Code.
My system has a welcome message. I use MailGun to send it.
The problem I have is that the message now is an HTML file, so I would like to let the HTML file in my server, read it using Cloud Code and pass that info to MailGun.
Can I read a local text file using Cloud Code and have it in my program as a string?
Should I save that file in my public folder or in the same folder than my cloudcode program?
I'm not confident with MailGun, but I believe it should work like MailChimp or Mandrill. If so, you should be able to store on MailGun your whole HTML template and just have some template_vars to complete.
This is a sample code of our own way to send mail with HTML thanks to the Mandrill system
Parse.Cloud.define("sendMailTemplate", function(request, response) {
var emails = request.params.emails;
var template_name = request.params.template_name;
var template_merge_content = request.params.template_merge_content;
var subject = request.params.subject;
var Mandrill = require('cloud/mandrillTemplateSend.js');
if (subject === undefined) {
subject = 'Mail sent by Mandrill';
body = subject;
}
Parse.Config.get().then(function(config) {
Mandrill.initialize(config.get('Mandrill_key'));
}).then(function() {
_.each(emails, function(email) {
Mandrill.sendTemplate({
template_name: template_name,
template_content: [{
name: template_merge_content.username,
content: ''
}],
message: {
text: '',
subject: subject,
from_email: 'contact#yourdomain.com',
to: [{
email: email,
name: template_merge_content.username
}],
merge_vars: [{
rcpt: email,
vars: template_merge_content
}],
},
async: false
});
});
}).then(function() {
response.success('Success');
}, function(error) {
response.error(error);
});
});
This object template_merge_content is quiet important. It's an object where is saved all the dynamic vars which are send to complete your HTML mail.
According to http://blog.mailgun.com/transactional-html-email-templates/ it seems you have same kind of method to send your mail.
So final advice would be to NOT store your HTML template within any Parse's class, or to save it within https://parse.com/docs/js/api/symbols/Parse.Config.html

Resources