I have the following code for viewing my webcam directly via a publicly accessible link.
<!DOCTYPE html>
<html>
<head>
<title>webRTC Test</title>
</head>
<script type = "text/javascript">
function init()
{
if(navigator.webkitGetUserMedia)
{
navigator.webkitGetUserMedia({video:true}, onSuccess, onFail);
}
else
{
alert('webRTC not available');
}
}
function onSuccess(stream)
{
document.getElementById('camFeed').src = webkitURL.createObjectURL(stream);
var src = document.getElementById('camFeed').getAttribute('src');
document.getElementById('streamLink').href = src;
}
function onFail()
{
alert('could not connect stream');
}
</script>
<body onload = "init();" style="background-color:#ababab;">
<div style="width:352px; height:625px; margin:0 auto; background-color:#fff;">
<div>
<video id ="camFeed" width="320" height="240" autoplay>
</video>
</div>
<div>
<canvas id="photo" width="320" height="240">
</canvas>
</div>
<div style="margin: 0 auto; width:82px;">
<a id="streamLink">Visit Stream</a>
</div>
</div>
</div>
</body>
</html>
The link generated in the anchor tag is something like:
blob:http%3A//sitename.com/7989e43a-334r-4319-b9c5-9dfu00b00cd0
And upon visiting chrome tells me "Oops! This link appears to be broken."
Help appreciated!
The File API spec defines URL.createObjectURL. There are a couple of sections that make what you're trying to do impossible in a browser that follows the spec.
Section 11.5 says:
The origin of a Blob URI must be the origin of the script that called URL.createObjectURL. Blob URIs must only be valid within this origin.
In other words, the URIs returned by createObjectURL can only be used within the context of the website that created them (see RFC6454: The Web Origin Concept for a more precise definition of what the HTML specs mean by “origin”). You can't visit a URL returned by createObjectURL directly.
Section 11.6 says:
This specification adds an additional unloading document cleanup step: user agents must revoke any Blob URIs created with URL.createObjectURL from within that document.
This means that even if you could visit the URL directly, as soon you you leave the page that called createObjectURL the URL that was created ceases to exist.
You must ensure that you’re using/testing your code at HTTP or HTTPs protocols --- because URL.createObjectURL has some issues at file:// protocol --- and it can’t be able to generate right BLOB for your video while using file:// ---- !!!
Your code won't work on localhost or your machine alone.
All you need is, upload this HTML document on the Net(just in case you are wondering on how to get Hosting for yourself, then try checkout Dropbox, you can upload your HTML page publicly and get access via Public Link for free or try some other product or simply get hosting for yourself). As you can see that this example http://www.html5rocks.com/en/tutorials/getusermedia/intro/ works perfectly in chrome, though the code that it is utilising is the same as yours. I hope this solution is of some help to your and others searching for an answer to this bug.
Also, you can then use an iframe to get access to the video element to perform operations on it.
Related
I've been searching today and have found some answers, such as this:
<head>
<title>Audio test</title>
<script type="text/javascript">
// #param filename The name of the file WITHOUT ending
function playSound(filename){
document.getElementById("sound").innerHTML='<audio autoplay="autoplay"><source src="' + filename + '.mp3" type="audio/mpeg" /><source src="' + filename + '.ogg" type="audio/ogg" /><embed hidden="true" autostart="true" loop="false" src="' + filename +'.mp3" /></audio>';
}
</script>
</head>
<body>
<button onclick="playSound('bing');">Play</button>
<div id="sound"></div>
</body>
For the answer above, I believe I just need to enter the correct file name (ex. mydomain.com/correctfilename.mp3) where 'filename' is in that script.
But I'm looking for something a little different and a little faster load-time wise. I'm wondering if I can have a 'default' Android notification sound played when the site is opened. I've found something similar to what I need right here:
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
But when I put that in the HTML file, it doesn't work, and I think it's because it's not javascript.
I know there are ways to access whatever your phone has that makes it vibrate, so I'm thinking there could be a way to access the pre-loaded sounds it has. Can I do this with a script?
I think you are asking if you can do something from the web page, not from a specific app on the device - for that way use WebView.
For any web page to access device services via the browser, there is the W3C Device API Working Group, which has produced a Vibration API, and even works already on Android Chrome Beta 39 and others like so:
navigator.vibrate(2000);
I'm not aware, however, of some way to play a default sound/vibration that follows the device environment like say, Windows API handles it.
I am working on a project that is intended to track users using Local Shared Objects. The user first visits page A, which has an embedded .swf that plants a Local Shared Object. I know it works by testing it my own flash cookies.
Upon visiting page B, another embedded .swf will attempt to retrieve the flash cookie and call an AJAX function if the cookie is present. Page B is what I am having trouble with. On this webpage is embedded a .swf object, along with an AJAX function. The following code is the HTML for page B. It includes the AJAX script, along with an embedded .swf.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
function databaseAndemail(){
$.get('http://www.mywebsite.com/databaseAndemail.php');
}
</script>
</head>
<body>
<object width="1" height="1">
<param name="CheckLSO" value="http://www.mywebsite.com/CheckLSO.swf">
<embed src="http://www.mywebsite.com/CheckLSO.swf" width="1" height="1">
</embed>
</object>
</body>
The problem is not with the AJAX function, nor the PHP script, because I know that works. The problem may lie within the .swf script that is meant to check the LSO. This is the AS3 script called CheckLSO.swf:
public function Main():void
{
//Check for a LSO
var myLocalData:SharedObject = SharedObject.getLocal("myData");
if (myLocalData.data.uname != null){ //LSO exists, so call AJAX function to update database and send email.
if (ExternalInterface.available){
ExternalInterface.call("databaseAndemail");
}
};
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
I'll include the AS3 script that sets the cookies here for your information (again, I've tested this one and it works):
public function Main():void
{
// Create a new SharedObject
var myLocalData:SharedObject = SharedObject.getLocal("myData");
// Save data to the SharedObject
myLocalData.data.uname = "ERE";
myLocalData.flush();
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
To sum it up, I think for some reason the Javascript function is not being called by External Interface. I know the cookie is set, I know the AJAX works, and I know the PHP script works (I haven't included the PHP, it seems like it would be outside the scope of this question). Both .swf scripts are debugged. I use FlashDevelop with Flex 4. These are really simple scripts, so I can't think of anything else that might be going wrong. Any ideas??
Might be the script access setting. On the embed, try including the param allowscriptaccess: "always". External Interface calls will fail without it.
<object width="1" height="1">
<param name="CheckLSO" value="http://www.mywebsite.com/CheckLSO.swf">
<param name="allowscriptaccess" value="always">
<embed src="http://www.mywebsite.com/CheckLSO.swf" width="1" height="1"></embed>
</object>
Better yet, use swfObject 2 to embed your swf.
SwfObject
I want to use Jquery or javascript to get the raw content (mean everycharacter) of an Iframe. It sounds simple but I'm still struggling with finding the right way for it.
For now it is only a XML content in the Iframe though.
Here the code:
$(function() {
var xmlContent = $("#CFrame").contents().find("*").text();
// The magic
$('#SResult').xslt({xml: xmlContent, xslUrl: 'stylesheet/designSS.xsl'});
});
The html page
<form id="searchForm" method="GET" target="ContentFrame" action="http://125.235.8.210:380/search" onSubmit="processContent()">
.....
</form>
</div>
<div id="SResult">
</div>
<iframe id="CFrame" name="ContentFrame" frameborder="1" height="2000px" width="1000px" scrolling="no" src="stylesheet/test.xml"></iframe>
</body>
Thanks,
Disclaimer: I'll answer your question regardless of whether it is actually an elegant solution to your problem. Joseph seems to take that as the question. I would say he is probably right to do so.
It won't work trying to get the frame using mimetype text/xml. The browser will proceed and 'translate' the XML into HTML. That's why it doesn't sound so simple. This way it is actually impossible.
I present you with a simple work-around for this problem.
<html>
<head>
<script>
function getXmlContents() {
/*
Note: Because of security reasons, the contents of a document can be accessed from another document only if the two documents are located in the same domain.
http://www.w3schools.com/jsref/prop_frame_contentdocument.asp
*/
var iframeDocument = document.getElementById('greetingFrame').contentDocument;
if (iframeDocument == null)
return undefined;
var xmlContainer = iframeDocument.getElementById('xmlContainer');
if (xmlContainer == null)
return undefined;
return xmlContainer.innerText == null ? xmlContainer.textContent : xmlContainer.innerText;
};
</script>
</head>
<body>
<iframe id="greetingFrame" src="helloworld.html" onload="alert(getXmlContents())">
</iframe>
</body>
</html>
The contents of the XML are wrapped inside an HTML (helloworld.html):
<html>
<body>
<script id="xmlContainer" type="text/xml">
<?xml version="1.0" encoding="UTF-8"?>
<title>
Hello world
</title>
</script>
</body>
</html>
I've successfully tested this in Chrome, Firefox and IE.
Of course you would have to wrap your XML documents inside a HTML script tag as indicated above. The XML can also be wrapped in a different tag, if you'd like it rendered for example, but you'd have to encode the XML using html encoding. This needs to be done on the server-side. A very simple (php/ruby/python/etc) script would suffice.
If your XML resides on your domain, you are better off with AJAX, especially using the jQuery library, which parses it for you and make it ready for immediate manipulations.
If it does not live on your domain, then you can't access it via AJAX unless the remote server and your client's browser both support CORS.
You have options though:
If the remote server's API supports JSONP, use it instead of XML. Then you can use jQuery to retrieve JSONP data or roll your own script loader.
Or use your server to proxy the XML for you. Servers are not restricted to the Same Origin Policy. Create an API on your server that relays your form data to the remote server and retrieve the remote page - all as if your server was the browser. Then forward the results back to you.
I am having trouble getting a working example that reads metadata from a WebVTT file, which was specified by the <track> element of a <video> in an HTML5 page. To be clear, I am not talking about reading the metadata out of the video file itself (as you would with an MPEG Transport Stream, for instance). What I'm talking about is the <track> element that is used for captioning videos. One of the attributes of a <track> is kind, which can be specified as any of the following values:
Subtitles
Descriptions
Captions
Navigation
Chapters
Metadata
I am trying to use the metadata type to access text stored in the corresponding WebVTT file, which I intend to manipulate using JavaScript. I know this is possible, as it is mentioned by Silvia Pfeiffer as well as by the maker of Captionator, which is the JavaScript polyfill that I am using to implement the functionality of interpreting the <track> tags. However, I just can't get it to work.
My code is based on the Captionator documentation's captions example. I added a button to retrieve the metadata and display it when I click the button. Unfortunately it keeps displaying "undefined" instead of the metadata. Any ideas what I might be doing incorrectly? Alternatively, does anyone know where a working example is that I could take a look at? I can't find one anywhere.
If you care to take a look at my code, I've included it below:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Video Closed Captioning Example</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" media="screen" href="js/Captionator-v0.5-12/css/captions.css"/>
</head>
<body>
<h1>HTML5 Video Closed Captioning Example</h1>
<div>
<p id="metadataText">Metadata text should appear here</p>
<input type='button' onclick='changeText()' value='Click here to display the metadata text'/>
</div>
<video controls autobuffer id="videoTest" width="1010" height="464">
<source src="http://localhost:8080/Videos/testVideo.webm" type="video/webm" />
<source src="http://localhost:8080/Videos/testVideo.mp4" type="video/mp4" />
<!-- WebVTT Track Metadata Example -->
<track label="Metadata Track" kind="metadata" src="http://localhost:8080/Videos/Timed_Text_Tracks/testVideo_metadata.vtt" type="text/webvtt" srclang="en" />
</video>
<!-- Include Captionator -->
<script type="text/javascript" src="js/Captionator-v0.5-12/js/captionator.js"></script>
<!-- Example Usage -->
<script type="text/javascript" src="js/Captionator-v0.5-12/js/captionator-example-api.js"></script>
<script type="text/javascript">
window.addEventListener("load",function() {
captionator.captionify(null,null,{
debugMode: !!window.location.search.match(/debug/i),
sizeCuesByTextBoundingBox: !!window.location.search.match(/boundingBox/i),
enableHighResolution: !!window.location.search.match(/highres/i),
});
var videoObject = document.getElementsByTagName("video")[0];
videoObject.volume = 0;
document.body.appendChild(generateMediaControls(videoObject));
},false);
function changeText() {
document.getElementById('metadataText').innerHTML = testVar;
var cueText = document.getElementById("video").tracks[0].activeCues[0].getCueAsSource();
document.getElementById('metadataText').innerHTML = cueText;
}
</script>
</body>
</html>
My WebVTT file looks like this:
WEBVTT
0
00:00.000 --> 00:04.000
Testing 1 2 3 . . .
The way you're accessing the cue is correct - no problems there (although there will be a change in Captionator 0.6 from the .tracks property to the .textTracks property to be more in line with the specification. If you can bear the occasional bug I would recommend using 0.6 for its greater standards compliance - I've written the below code to use .textTracks - substitute for .tracks if you'd like to continue using the stable branch.)
The issue relates to the loading of the text tracks themselves. At the moment, you're not actually telling Captionator to load the track. Because this happens asynchronously, and on request, there is that inevitable delay where their content isn't available, you'll need to write your code in a way which accommodates for loading time and the potential load error.
You're also not waiting for Captionator itself to load - potentially a user could unknowingly click the button before this had occurred - triggering a nasty JavaScript error. This won't be such a problem when testing on your local box, but as soon as you deploy to the internet you'll be seeing all sorts of race conditions and other nasties. Consider disabling the button until both the page and the caption data have loaded.
I've tried to make the Captionator API as close as possible to the actual JS API which will be landing in browsers very soon - so in future this will be the same way you'll interact with the native browser functionality. As soon as the functionality is available natively, Captionator will bow out of the way, and your code should (assuming they don't change the API again!) just work with the native API.
First of all, you need to actually request that Captionator load the content. This is done my setting the 'display mode' of the track to SHOWING, or 2.
var video = document.getElementByID("myVideo");
video.textTracks[0].mode = 2; // SHOWING
Alternately, you can assign the status of a track to HIDDEN (1) - which still triggers a load, and cueChange events will still fire - but won't paint cues to screen. In Captionator, I don't paint metadata tracks to screen at all, but the (buggy) WebKit API in development will.
video.textTracks[0].mode = 1; // HIDDEN
Then you need to listen for when the cues are loaded and available:
video.textTracks[0].onload = function() { /* Your Code Here... */ }
Or when something goes wrong:
video.textTracks[0].onerror = function() { /* Whoah, something went wrong... */ }
Once the content is loaded, you can access the TextTrack.cues array (well, technically a TextTrackCueList.) Before the load has occurred, the TextTrack.cues property will be null.
var myCueText = video.textTracks[0].cues[0].text;
Be aware that Captionator parses the cue text of every cue, except when the track kind is metadata - so ensure you assign the correct track kind. You might end up with data or tags Captionator thinks are 'invalid' being thrown out. You can turn this check off for regular cues as well, with by setting the processCueHTML option to false.
With that in mind, here's how I'd rewrite your code:
<div>
<p id="metadataText">Metadata text should appear here</p>
<input type='button' onclick='changeText()' value='Click here to display the metadata text' id="changetext" disabled />
</div>
<video controls autobuffer id="videoTest" width="512" height="288">
<!-- Your video sources etc... -->
<!-- The metadata track -->
<track label="Metadata Track" kind="metadata" src="metadata.vtt" type="text/webvtt" srclang="en" />
</video>
<!-- Include Captionator -->
<script type="text/javascript" src="captionator.js"></script>
<script type="text/javascript">
document.addEventListener("readystatechange",function(event) {
if (document.readyState === "complete") {
captionator.captionify();
document.querySelectorAll("#changetext")[0].removeAttribute("disabled");
}
},false);
function changeText() {
// Get the metadataText paragraph
var textOutput = document.querySelectorAll("#metadataText")[0];
// Get the metadata text track
var metadataTrack = document.querySelectorAll("video")[0].textTracks[0];
if (metadataTrack.readyState === captionator.TextTrack.LOADED) {
// The cue is already ready to be displayed!
textOutput.innerHTML = metadataTrack.cues[0].text;
} else {
// We check to see whether we haven't already assigned the mode.
if (metadataTrack.mode !== captionator.TextTrack.SHOWING) {
textOutput.innerHTML = "Caption loading...";
// The file isn't loaded yet. Load it in!
metadataTrack.mode = captionator.TextTrack.SHOWING; // You can use captionator.TextTrack.HIDDEN too.
metadataTrack.onload = function() {
textOutput.innerHTML = metadataTrack.cues[0].text;
}
metadataTrack.onerror = function() {
textOutput.innerHTML = "Error loading caption!";
}
}
}
}
</script>
Here, we're disabling the button, preventing users on slow connections (or just somebody with very quick reflexes!) from hitting it before either Captionator or the metadata track are ready, and listening to a load event - at which point we re-enable the button, and can retrieve the cue text as normal.
You may need to load your metadata VTT file via Ajax and parse and display it yourself.
I looked at the example from the HTML5 Doctors' article on video subtitling. They're using Playr, so I checked out its source code, and they're definitely requesting the VTT file asynchronously and parsing the content once it's loaded.
I was able to load the contents of the VTT file and dump it into the specified element with the following code:
function changeText() {
var track = document.getElementById("videoTest").querySelector("track");
var req_track = new XMLHttpRequest();
req_track.open('GET', track.getAttribute("src"));
req_track.onreadystatechange = function(){
if(req_track.readyState == 4 && (req_track.status == 200 || req_track.status == 0)){
if(req_track.responseText != ''){
document.getElementById("metadataText").innerHTML = req_track.responseText;
}
}
}
req_track.send(null);
}
I'm not familiar with Captionator, but it looks like it has some capabilities for parsing VTT files into some sort of data structure, even if it doesn't necessarily support the metadata track type. Maybe you can use a combination of this code and Captionator's existing VTT parser?
Right now I can use this URL to request a Google Static Maps image successfully:
http://maps.google.com/staticmap?center=37.687,-122.407&zoom=8&size=450x300&maptype=terrain&key=[my key here]&sensor=false
However, the second I use JQuery or any direct javascript to set an image's src to the above url, Google passes back a Error 400:
"Your client has issued a malformed or illegal request."
I've read that this is usually from the key being incorrect, but my key is clearly being passed.
This is how I'm setting the image dynamically:
document.getElementById('my-image-id').src = "http://maps.google.com/staticmap?center=37.687,-122.407&zoom=8&size=450x300&maptype=terrain&key=[my key here]&sensor=false"
I've replaced [my key here] with my correct key, and it still doesn't work. When I request the same url through the browser, it's fine. I've confirmed that the correct referrers are getting passed as well.
Any ideas?
Does this code work for you (it works for me -- be sure to insert your key)?
<html>
<head>
<script language="javascript">
function swap() {
document.getElementById('my-image-id').src = "http://maps.google.com/staticmap?center=37.687,-122.407&zoom=8&size=450x300&maptype=terrain&key=&sensor=false"
}
</script>
</head>
<body>
<img src="http://www.google.com/intl/en_ALL/images/logo.gif" width="450" height="300" onClick="swap();" id="my-image-id" />
</body>
</html>
You have a possible typo with the g on the end here:
&key=[my key here]g
The problem is with the key. Register for a new key and append with the url. It will work fine. I even was faccing same problem. It was working with direct paste in address bar of browser. But in production it was not working. I put new key and it worked fine both in production and browser.