Three.js webgl video texture CORS issue on safari - three.js

In my vuejs nuxt static site hosted on netlify, I'm trying to use a mp4 video hosted on Vimeo Pro as a video texture in three.js with the following (simplified version)
// create video dom element
let video_ele = document.createElement('video')
video_ele.className = 'video_texture'
video_ele.setAttribute('playsinline', true)
video_ele.muted = true
video_ele.loop = true
video_ele.autoplay = true
video_ele.crossOrigin = 'anonymous'
video_ele.src = "https://vimeo-video-url-here.....mp4"
document.body.appendChild(video_ele)
// create video texture from video
let video_texture = new THREE.VideoTexture(video_ele)
video_texture.minFilter = THREE.LinearFilter
video_texture.magFilter = THREE.LinearFilter
video_texture.format = THREE.RGBFormat
// map video texture to material
material = new THREE.MeshStandardMaterial({
color: 0xa8a8a8,
map: video_texture
})
Everything else works fine on chrome, firefox and also chrome mobile browser.
but in Safari 13 on mac os and ios 13, i get this error thrown in the console
THREE.WebGLState:
SecurityError: The operation is insecure.
I tried replacing the vimeo video with urls of other videos hosted elsewhere and i get same error in safari only.
I'm pretty sure its a CORS issue because when i replace the vimeo or external url with a static video hosted within same host (netlify), it works fine.
I also tried appending a timestamp to the video url just to be sure its not a cache issue, but still no luck
Wondering how can i make this work with an externally hosted video like vimeo?

Upon further testing, it seems to me that the issue was caused by the 302 redirect to their CDN that happens when you use a vimeo file url.
As #gman pointed out, there's a similar issue on Soundclound and i found that the solution provided there worked for my case too.
How to get Safari 12 to process audio from soundcloud?
I solved it by making an async fetch request to get the CDN url and then passing it to the video.src. Works in safari mac and ios (13) now now!
async function getMediaURLForTrack(texture_to_update, passed_url) {
await fetch(passed_url, {
method: 'HEAD'
})
.then((response) => {
texture_to_update.src = response.url
});
}

Related

RecordRTC - Playing recordings on Safari fails

I am using RecordRTC to allow my application user to record their video and upload. This works perfectly fine with Chrome and Mozila Firefox but Safari having trouble playing recorded videos.
I research for the same and found mimeType: 'video/webm\;codecs=vp8' to be used for safari. However this still won't work on Safari browsers. (mac OS x and iOS)
Can someone please help me with this? I have multiple users working on different operating systems and working on different browsers and I want to make sure RecordRTC works for all of them.
I am open to change/ switch to any other alternative if available to implement this feature with cross-browser support of course.
I found Twilio but I am not sure whether Twilio supports standalone recordings or not? I mean I just want single user to go on a page record a video and upload.
Please see below my RecordRTC configuration if it helps:
const options = {
type: 'video',
mimeType: 'video/webm\;codecs=vp8',
bitsPerSecond: 128000,
timeSlice: 1000
};
After user completes the recording, I am converting it to a blob and append it to the formData to save it to the server:
var recordedBlob: Blob = recordRTC.getBlob();
formData.append('files', recordedBlob, this.courseComponent?.courseComponent?.name + '.webm');
This recorded video plays fine in Chrome and Firefox but in Safari it Fails.
Please if you can guide me through this it will be great help to me.
Thanks.
Below are the console log snaps:
1.browser does not support media recorder api
when tried to play the recorded video
says browser does not support media recorder api and try using whammyRecorder

Image hosted internally inaccessible on MS Teams client

We have enabled Bot Framework app in our corporate Teams and we want to use AdaptiveCards to present rich content to users. For example, we are sending AdaptiveImage containing url pointing to corporate image store.
Sample code:
new AdaptiveImage
{
Size = AdaptiveImageSize.Small,
Url = new Uri("https://corporate-storage.com/images/image1.png"), // This is image not hosted publicly.
AltText = "Some text"
}
This works fine in WebChat client as the url is just appended to the src attribute of the img HTML tag. However in MS Teams it seems that it is preprocessed by some weird proxy / MITM and the url results in:
https://urlp.asm.skype.com/v1/url/content?url=https%3a%2f%2fcorporate-proxy.com%2fimages%2fimage1.png
When we try to browse the url to see where why the picure is not rendered we see empty page with 502 response code in debugger.
Is there a way how to force MS Teams to not alter src attributes of pictures.
For rendering image in adaptive card, it has to be hosted in public content-delivery network (CDN). Here the official document link.
It worked in WebChat client because in browser your authentication is already cached where as in Teams App there is no cache and the image requires authentication.
You need to host the image in public domain or Azure Blob storage to make it work.
I also have not found a way to resolve that, some gays also ask about this problem.
So, I use tampermonkey to load a JS code piece like this.
// ==UserScript==
// #name New Userscript
// #namespace http://tampermonkey.net/
// #version 0.1
// #description try to take over the world!
// #author You
// #match https://teams.microsoft.com/*
// #icon https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// #grant none
// ==/UserScript==
(function() {
'use strict';
setInterval(function(){
$('img').each(function(){
if($(this).attr('src').startsWith("https://urlp.asm.skype.com/v1/url/content?url=https%3a%2f%2fp.datadoghq.com")){
let datadogUrl=$(this).attr('src').replace("https://urlp.asm.skype.com/v1/url/content?url=","")
datadogUrl=decodeURIComponent(datadogUrl)
$(this).attr('src', datadogUrl);
}
})
}, 5000);
})();
And use Teams Web, not Teams App.

How do I detect when embedded Youtube video is playing?

UPDATE (July 2020): I was able to get a mostly working version of this. See my answer to the related question here.
In my angular Nativescript iOS app, I have a webview set up to play youtube videos. Following a method similar to this question here, I can get the youtube video to load and play automatically, using the Youtube Iframe API. But how do I detect when the video actually starts playing (after it is loaded)?
The Iframe API has events for this purpose, like "onStateChange". But, because my youtube code is "stuck" inside the webview, I am currently not able to read when events are fired from that webview.
In Nativescript, there is a nativescript-webview-interface plugin for this purpose, but I can't get it to work. I have put my code below. If that is the way to go, what is the correct code to get it working?
(I don't want to use the nativescript-youtube plugin because that brings in youtube's quotas, which are regularly shrinking. )
Code I Have Tried:
To get the youtube player to activate, I have put all of the relevant youtube code inside the webview. That works to play the video, but not yet to get the event of when the player starts playing. To do what I want to do, I need to have some way of inserting that code into my app WITHOUT trapping it in the webview. Or, have some way of communicating inside the webview.
To try to communicate with the webview, I have tried the nativescript-webview-plugin:
$ tns plugin add nativescript-webview-interface
html:
<web-view src="{{youtubeCode}}" #webView ></web-view>
ts:
import {WebView, LoadEventData} from "tns-core-modules/ui/web-view";
let webViewInterfaceModule = require('nativescript-webview-interface');
...
export class ...{
#ViewChild('webView') webView: ElementRef;
public youtubeCode = [code that youtube provides in its IFrame API]
ngOnInit(): void {
this.setupWebViewInterface();
}
setupWebViewInterface() {
let webView: WebView = this.webView.nativeElement;
this.oWebViewInterface = new webViewInterfaceModule.WebViewInterface(webView, '~/www/index.html');
this.youtubeListen()
}..
youtubeListen(){
this.oWebViewInterface.on('onStateChange', (eventData)=>{ //'onStateChange' is the event provided in the Youtube Iframe API
console.log('event data = ' + eventData) //***this is the key part I want to work.
});
}
RESULT: ERROR TypeError: undefined is not an object (evaluating 'this.webView.ios.constructor')
This is a problem in the plugin's index.ios.js file. If I comment out the offending line, then the errors go away, but then nothing happens
..

file upload not working on internet explorer 8 and 9

function uploadFile(){
var file = $("file1").files[0];
var formdata = new FormData(); formdata.append("file1", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "upload.php";
ajax.send(formdata);
}
Error1: Unable to get value of the property '0': object is null or undefined
Error2: ForData not supported.
The FormData API is not supported by IE8 or IE9. It was only added in IE10. If you want to support these old browsers, then you cannot use modern HTML5 APIs.
There is a jQuery Forms plugin which does work in old IE versions and can allow you to upload files via ajax. I've used it myself and it is very effective. You can download it here: http://malsup.com/jquery/form/. You will probably need to rewrite your code a fair bit in order to use it as it's quite different conceptually to the HTML5 FormData API, but at least you'll get something that will work across all the browsers you want to support.
You could also try looking to see if there's a polyfill for FormData which would allow you to keep using your existing code. A quick google turned up this one, which I found listed here. I haven't tried it so can't vouch for it, but the polyfills listed by Modernizr on that list are generally pretty good.

Opening a PDF file in Windows Phone

I'm developing an app for Windows Phone 7 and I'm using a Phonegap template for it.
Everything looks perfect, but now I’m stuck trying to open a PDF file in the browser.
I tried the following but that doesn’t work because the url of the PDF exceeds the 2048 character limit (it’s a data url). This code runs after the deviceReady event was fired.
var ref = window.open('http://www.google.com', '_blank', 'location=no');
ref.addEventListener('loadstart', function () { alert(event.url); });
Now, I'm trying to save the PDF file to storage and then I'm trying to have it opened by the browser, but the browser doesn't show anything. I'm editing the InAppBrowser.cs code from cordovalib and I added the following lines before calling browser.Navigate(loc);
private void ShowInAppBrowser(string url)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
FileStream stream = store.OpenFile("test.pdf", FileMode.Create);
BinaryWriter writer = new BinaryWriter(stream);
var myvar = Base64Decode("the big data url");
writer.Write(myvar);
writer.Close();
if (store.FileExists("test.pdf")) // Check if file exists
{
Uri loc = new Uri("test.pdf", UriKind.Relative);
...
}
}
This code is returning the following error:
Log:"Error in error callback: InAppBrowser1921408518 = TypeError: Unable to get value of the property 'url': object is null or undefined"
I don’t wanna use ComponentOne.
Any help would be greatly appreciated!
You cannot open pdf files from the isolated storage in the default reader for PDF files. If the file is online e.g. it has a URI for it, you can use WebBrowserTask to open it since that will download and open the file in Adobe Reader.
On Windows Phone 8 you actually can open your own file in default file reader for that extension, but I am not sure how that will help you since you target PhoneGap and Windows Phone 7.
Toni is correct. You could go and try to build your own viewer (which would be the same thing as using C1, but with more time involved). I worked on a port of iTextSharp and PDFSharp for WP7, but neither of which are PDF Viewers. They are good for creating PDFs and parsing them some (but to render them there is more work involved). This has been a personal quest of mine, but honestly the best I have gotten is to be able to extract some images from the PDF (and none of the text)
try this
var installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assets = await installedLocation.GetFolderAsync("Assets");
var pdf = await assets.GetFileAsync("metro.pdf");
Windows.System.Launcher.LaunchFileAsync(pdf);
This worked correctly on my Device.

Resources