---------------Introduction-------------------------------------
I'm working on an IP camera project in a gym. There are 16 cameras. Each camera films an apparatus, then broadcasts its content on a local network in rtsp.
All rtsp streams are saved as an m3u8 playlist on a web server via ffmpeg.
The ffmpeg command used is: ffmpeg -v verbose -rtsp_transport tcp -i rtsp://id:mdp#192.168.0.%%x:554/h265Preview_01_main -preset ultrafast -map 0 -map -0:a -c :v copy -c:a copy -f hls -hls_time 1 -segment_time 2 -hls_list_size 2000 -hls_flags delete_segments+append_list+omit_endlist C:[...]\WebServer\Data%%x\Rec.m3u8
The web server displays the web pages of each apparatus area, The videos are then played via video-js.
So far everything is working fine (except for a few bugs / data corruption when retrieving the different video streams).
My concern comes from a feature that I would like to add.
Indeed I would like to be able to extract part of the video to then be able to recover this extract and publish it on the networks.
At first I looked at the MediaCapture API but it is not compatible with the tablets used (iOS 12.5).
---------------The Problem-------------------------------------
So I try to go through the recovery of the currently read segment, then send a php request to launch a script on the server which will go and recover this segment and the following ones (depending on the desired recording time) to merge them into an mp4 video.
My problem is that I can't retrieve this information....
I set useCueTags: true but textTracks() remains empty...
If anyone can help me see what I did wrong, thanks :)
Here is an example of one of the webpages
<?php include('../Headers.php'); ?>
<body>
<section>
<button id="pointer">Point de Sauvegarde</button>
<button id="download">Enregistrement du point de sauvegarde</button>
<div class="slidecontainer">
<input type="range" min="10" max="100" value="50" step="10" class="slider" id="TempoRec">
<pre id="slideroutput">
</pre>
</div>
</section>
<section>
<div class="gauche">
<video-js id="player" class="video-js vjs-fluid" controls preload="auto">
</video-js>
</div>
<div class="droite">
<video id="recording" controls loop muted></video>
</div>
</section>
<?php include('../footer.php'); ?>
<script src="http://127.0.0.1/dist/video-js/video.js"></script>
<script src="http://127.0.0.1/dist/videojs-seek-buttons.min.js"></script>
<script src="http://127.0.0.1/dist/videojs-frame-by-frame.js"></script>
<script>
var player = videojs('player',{liveui:true,playbackRates: [0.1,0.3,0.5,1],controlBar: {volumePanel:false,muteToggle:false}});
player.src({
src:'http://127.0.0.1/Data/12/ZoneArc.m3u8',
type:'application/x-mpegURL',
nativeTextTracks: false,
nativeAudioTracks: false,
nativeVideoTracks: false,
overrideNative: true,
useCueTags: true
});
player.seekButtons({
forward: 5,
back: 10
});
player.frametoframe({
forward: 0.1,
back: 0.1
});
let tracks = player.textTracks();
var segmentMetadataTrack;
console.log(tracks.length);
for (let i = 0; i < tracks.length; i++) {
if (tracks[i].label === 'segment-metadata'){
segmentMetadataTrack = tracks[i];
let previousPlaylist;
segmentMetadataTrack.on('cuechange', function(){
let activeCue = segmentMetadataTrack.activeCues[0];
if (activeCue) {
if (previousPlaylist !== activeCue.value.uri) {
console.log('Switched from rendition ' + previousPlaylist +
' to rendition ' + activeCue.value.playlist);
}
previousPlaylist = activeCue.value.uri;
}
});
}
}
</script>
</body></html>
I'm expecting the variable tracks to be filled with a least the segment-metadata track but it stay empty whatever i do...
You can add a listener for loadedmetadata and check for the tracks then. If you check too soon the track won't have been added yet.
player.on('loadedmetadata', function() {
console.log(player.textTracks().length);
});
Thanks #misterben, works like a charm now !
Script is now like that :
<script>
var player = videojs('player',{liveui:true,playbackRates: [0.1,0.3,0.5,1],controlBar: {volumePanel:false,muteToggle:false}});
player.src({
src:'http://127.0.0.1/Data/12/ZoneArc.m3u8',
type:'application/x-mpegURL',
nativeTextTracks: false,
nativeAudioTracks: false,
nativeVideoTracks: false,
overrideNative: true,
useCueTags: true
});
player.seekButtons({
forward: 5,
back: 10
});
player.frametoframe({
forward: 0.1,
back: 0.1
});
player.on('loadedmetadata',function(){
let tracks = player.textTracks();
var segmentMetadataTrack;
console.log(tracks.length);
for (let i = 0; i < tracks.length; i++) {
if (tracks[i].label === 'segment-metadata'){
segmentMetadataTrack = tracks[i];
let previousPlaylist;
segmentMetadataTrack.on('cuechange', function(){
let activeCue = segmentMetadataTrack.activeCues[0];
if (activeCue) {
if (previousPlaylist !== activeCue.value.uri) {
console.log('Switched from semgent ' + previousPlaylist +
' to rendition ' + activeCue.value.uri);
}
previousPlaylist = activeCue.value.uri;
}
});
}
}
});
</script>
Need to send current ts segment to server via php now !
Related
I am building an application that downloads a user's now playing data from Spotify and then serves the information as a webpage widget that the user can add to their livestreams to show their viewers what music they are playing in their livestream.
On the backend I have a Flask server that fetches the information and then pushes an update on the frontend via a websocket - this is to avoid having to refresh the page. On the web page I have an Updater.js file that receives the information from the backend and updates the widget to display the new song.
The problem I am having is that I am unable to update the cover image using the Updater.js script. At first I did so by saving the image under the same name and triggering an update on the image by adding a ?t=timestamp to the end of the image url. It worked for awhile, until I updated my Firefox and it stopped working on both Firefox and Chrome.
I changed it so that the Flask server saves the image with a number attached that increments, and then deletes the previous image. I have tried updating the page to display the new image, but it seems that the web page cannot access my server's static files. I have tried different link formats, but I haven't found anything that works so far.
Is there some way that I can access images in the static folder using JavaScript and update it on the page, or will I only be able to achieve this using render_template?
Updater.js:
// This file listens to the backend, and updates the widget when a new song has started playing
// Use this function to update the cover image without refreshing the page
function refresh_image(url)
{
let image = document.getElementById("cover_art");
image.src = url
console.log(image.src)
}
const socket = new WebSocket("ws://" + location.host + "/update");
const image_link = "http://localhost:"
console.log("Communication between server and browser is initialized")
// Listen for data being pushed from the backend
socket.addEventListener("message", package => {
let song = "";
let artists = "";
let port = "";
let image_num = "";
let artists_done = false;
let song_done = false;
let port_done = false;
console.log(package.data)
// Seperate data into variables
for (let i = 0; i < package.data.length; i++)
{
// Artists
if (artists_done == false)
{
while (package.data[i] != ";")
{
artists += package.data[i];
i++;
};
i++;
artists_done = true;
};
// Song
if (song_done == false)
{
while (package.data[i] != ";")
{
song += package.data[i];
i++;
};
i++;
song_done = true;
};
// port
if (port_done == false)
{
while (package.data[i] != ";")
{
port += package.data[i];
i++;
};
i++;
port_done = true;
};
// Image_num
image_num += package.data[i];
};
// Assemble the image src
image_src = "/static/image" + image_num + ".jpg";
// Update widget
refresh_image(image_src)
document.getElementById("song_title").innerHTML = song;
document.getElementById("artists").innerHTML = artists;
console.log("Widget is successfully updated")
});
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="static/style.css">
<title>OBS Music Widget</title>
</head>
<body>
<script src="static/updater.js"></script>
<div id="widget">
<div id="cover"><img id="cover_art" src="{{url_for('static', filename='image.jpg')}}" alt="Song cover image"></div>
<div id="info">
<p id="song_title">{{ song }}</p>
<p id="artists">{{ artists }}</p>
</div>
</div>
</body>
</html>
I believe I asked the question in the right way, or at least I hope so. I'm trying to find a way to send data to the server (in this case I guess the server would be the ESP8266 since that's what the client's communicating with right?) every time there is a change in a range input (the purpose of this would be to allow the user of the led display to be able to see in real time the change in the display's brightness without needing to reload the page). I've found a few ideas online but I don't know if they're quite what I'm looking for, I don't know how to program in JavaScript yet (apart from a few examples here and there) but from what I can gather that's the only way I could implement this, but I don't quite know if I should be making the request in the script of the website or in the NodeMCU, as in, should I ask periodically for the variable from the MCU to see if there's any change in the range input, or should I try to post the data from the browser's side (which I don't know how to do either but if anyone can give me a hint of where to look it'd be much appreciated). Basically what I'm asking here is what method should I use or like what should I look into for doing it because I have no idea rn.
I apologize in advance for the many mixed concepts (and for my English btw) I might have misused or confused while writing this question, this is a project for one of my classes (I didn't actually chose it but I was tasked with making the code for the MCU and the webpage so I had to start learning from zero) and I wanted to make it a bit fancier but ended up being trickier than I thought. The idea is that the user connects to the micro and they can input the message to be displayed as well as a number of settings, amongst which is the brightness of the display.
maybe you can get I better idea of what I'm trying to do with this
<!DOCTYPE html>
<html lang="en">
<head>
<title>LED DISPLAY</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">
<script>
function includeHTML() {
var z, i, elmnt, file, xhttp;
/*loop through a collection of all HTML elements:*/
z = document.getElementsByTagName("*");
for (i = 0; i < z.length; i++) {
elmnt = z[i];
/*search for elements with a certain attribute:*/
file = elmnt.getAttribute("w3-include-html");
if (file) {
/*make an HTTP request using the attribute value as the file name:*/
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {elmnt.innerHTML = this.responseText;}
if (this.status == 404) {elmnt.innerHTML = "Page not found.";}
/*remove the attribute, and call this function once more:*/
elmnt.removeAttribute("w3-include-html");
includeHTML();
}
}
xhttp.open("GET", file, true);
xhttp.send();
/*exit the function:*/
return;
}
}
};
</script>
<body>
<div w3-include-html="header.html"></div>
<script>
includeHTML();
</script>
<div class="row">
<div class="column side">
</div>
<div class="column middle">
<h3>Brightness: <span id="mensaje"></span></h3>
<div class="slidecontainer">
<input type="range" min="1" max="15" class="slider" id="myRange">
<p><span id="demo"></span></p>
</div>
<script>
var slider = document.getElementById("myRange");
var output = document.getElementById("demo");
output.innerHTML = slider.value;
slider.oninput = function() {
output.innerHTML = this.value;
}
</script>
</div>
<div class="column side">
</div>
</div>
</body>
</html>
</body>
</html>
The code for the ESP8266 is also incredibly cringy but I suppose I should include it just in case
#include <FS.h>
#include <LittleFS.h> //The html and css files are used to replace the using strings as html code
#include <ESP8266WiFi.h>
//#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncWiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <EEPROM.h> //EEPROM 819: dirección(?; EEPROM 820: velocidad(?; EEPROM 821: brillo;
//EEPROM 822: largo del último mensaje guardado; EEPROM 823-1023: mensaje
const int ledPin = 2;
String lasped= "fast";
String ledState;
bool flag=0;
byte message_length;
//const char* fname;
const char* PARAM_INPUT_1 = "fname";
String inputMessage;
AsyncWebServer server(80);
void handleFormText(AsyncWebServerRequest *request)
{
String MiText = request->arg("miText");
Serial.print("MiText:\t");
Serial.println(MiText);
//String response = "<a href='/'> Go Back </a>";
//request->send(200, "text/html", response);
// redirección directa
request->redirect("/");
}
void save_message(){
int sd=823;
char the_letrero[200];
strcpy(the_letrero, inputMessage.c_str());
for(int i=0; i<(inputMessage.length()); i++){
EEPROM.write( sd , the_letrero[i]);
sd++;
}
EEPROM.write(800 , inputMessage.length());
EEPROM.write(822 , inputMessage.length());
EEPROM.commit();
yield();
}
void ReadMessage(){
int sd_read=823;
for(int i=0; i<EEPROM.read(822); i++){
Serial.print(char(EEPROM.read(sd_read)));
sd_read++;
//EEPROM.read(822)
}
Serial.print("\n");
yield();
}
DNSServer dns;
String processor(const String& var){
//Serial.println(var);
if (var == "MENSAJE"){
return inputMessage;
}
else if (var == "TEMPERATURE"){
//return getTemperature();
}
else if (var == "HUMIDITY"){
//return getHumidity();
}
else if (var == "PRESSURE"){
//return getPressure();
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
EEPROM.begin(1024);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
AsyncWiFiManager wifiManager(&server,&dns);
//reset settings - for testing
//wifiManager.resetSettings();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
wifiManager.setTimeout(180);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if(!wifiManager.autoConnect("AutoConnectAP")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
//Serial.begin(115200);
pinMode(ledPin, OUTPUT);
// Initialize LittleFS
if(!LittleFS.begin()){
Serial.println("An Error has occurred while mounting LittleFS");
return;
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
Serial.println(WiFi.localIP());
ReadMessage();
// Route to load style.css file
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/style.css", "text/css");
});
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/Home_page.html");
});
server.on("/message", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/Message_page.html");
});
server.on("/get", HTTP_GET, [](AsyncWebServerRequest *request){
//request->send(LittleFS, "/Msj.html");
String inputParam;
if (request->hasParam(PARAM_INPUT_1)) {
inputMessage = request->getParam(PARAM_INPUT_1)->value();
flag=1;
}
Serial.println(inputMessage);
//request->send(LittleFS, "/Msj.html");
request->send(LittleFS, "/Msj.html");
});
server.on("/mensaje", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", inputMessage.c_str());
});
/*server.on("/veloc", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", lasped.c_str());
});*/
// Start server
server.begin();
//InitServer();
yield();
}
void loop() {
// put your main code here, to run repeatedly:
if(flag=1)
{save_message(); flag=0;}
yield();
}
First of all, I would like to apologize for the horribly worded title; I have been trying to think of one for the past 20 minutes but I do not know a succinct way to describe the problem I am having. If anyone has a better suggestion, please let me know or edit the title if you are able to.
Background: In order to learn NodeJS, I am creating a chat server. When the user clicks the createRoomBtn, an event is created containing the name of the room the user just created, and sent to the socket.js module in app.js, app.js then appends the room to the array of rooms (these rooms are displayed as a list in the browser), and creates a broadcast event to all users including the active user.
Problem: Let's say there is an empty list, and user adds a new room, titled "NodeJS", this will display the room on the screen, and everything is fine and dandy. Now, if I was to add another room, Socket.io, for example, the browser renders the following result: Socket.io, NodeJS, NodeJS. If I was to add "Javascript", the result would be Javascript, Socket.io, NodeJS, Socket.io, Node.JS. Basically, the browser renders the list over and over again, and each time the list shrinks by one. I do not have the slightest idea of why this is happening. The weird thing is that if I press refresh, the browser renders the list correctly Javascript, Socket.io, NodeJS. What is going on?
socket.js:
module.exports = function(io, rooms) {
var chatrooms = io.of('/roomlist').on('connection', function(socket) { //io.of creates a namespace
console.log('Connection established on the server');
socket.emit('roomupdate', JSON.stringify(rooms));
socket.on('newroom', function(data) {
console.log(data);
rooms.push(data);
socket.broadcast.emit('roomupdate', JSON.stringify(rooms));
socket.emit('roomupdate', JSON.stringify(rooms));
})
})
var messages = io.of('/messages').on('connection', function(socket) {
console.log('Connected to the chatroom!');
socket.on('joinroom', function(data) {
socket.username = data.user;
socket.userpic = data.userPic;
socket.join(data.room);
})
socket.on('newMessage', function(data) {
socket.broadcast.to(data.room_number).emit('messagefeed', JSON.stringify(data));
})
})
}
chatrooms.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" href="../css/chatrooms.css">
<script src="//code.jquery.com/jquery-1.11.0.min.js"> </script>
<script src="/socket.io/socket.io.js"> </script>
<script>
$(function() {
var host = '{{config.host}}';
var socket = io.connect(host + '/roomlist');
socket.on('connect', function() {
console.log('connection established');
})
socket.on('roomupdate', function(data) {
$('.roomlist').html('');
var procData = JSON.parse(data);
for (var i = 0; i < procData.length; i++) {
var str = '<a href="room/' + procData[i].room_number + '"><li>'
+ procData[i].room_name + '<li></a>';
$('.roomlist').prepend(str);
console.log(str);
}
})
$(document).on('click', '#createRoomBtn', function() {
var room_name = $('#newRoomText').val();
console.log(room_name);
if (room_name != '') {
var room_number = parseInt(Math.random() * 10000);
socket.emit('newroom', {room_name: room_name, room_number: room_number});
$('#newRoomText').val('');
}
})
})
</script>
</head>
<body>
<div class="cr-userbox">
<img src="{{user.profilePic}}" class="userPic">
<h3 class="username">{{user.fullName}}| Logout</h3>
</div>
<div class="cr-container">
<h1> ChatRooms</h1>
<div class="cr-newroom">
<input type="text" id="newRoomText" autocomplete="off">
<input type="submit" id="createRoomBtn" value=" Create Room">
</div>
<div class="cr-roomlist">
<ul class="roomlist">
</ul>
</div>
</div>
</body>
</html>
Please let me know if more information/modules are required, and I will be happy to provide them.
Update1: As correctly suggested by alex-rokabilis, I have changed $('.roomlist').html() = '' to $('.roomlist').html(''), however, the problem continues to persist.
I'm not sure if this is the cause of your problem or not but you're getting nested list eliments because you have two opening <li> tags in your socket.on ('roomupdate') function
I believe the problem is how you render your rooms in the html part, not how socket.io sends the data.
You use $('.roomlist').html=''; but this is not doing anything! .html is a function in jquery so the right thing to do is $('.roomlist').html('');.
So basically you didn't erase the previous rooms but instead you only add more duplicates. Also something i noticed that is not part of your question, in your nodejs code you use: socket.broadcast.emit('roomupdate', JSON.stringify(rooms));
socket.emit('roomupdate', JSON.stringify(rooms));
if you want to broadcast something to all connected clients there is a function for it and also there is no need to stringify your data, socketio do this internally for you! So you could use something like this:
io.emit('roomupdate',rooms);
I am using tokbox trial for video chatting on my website. But the problem i am facing is that ::: User 1 can see and hear User 2 clearly. User 2 can see User 1 clearly, but user 2 couldnt here user 1. And code i am using
<html>
<head>
<title>Monkvyasa | Test</title>
<script src='http://static.opentok.com/webrtc/v2.2/js/opentok.min.js'></script>
<script type="text/javascript">
// Initialize API key, session, and token...
// Think of a session as a room, and a token as the key to get in to the room
// Sessions and tokens are generated on your server and passed down to the client
var apiKey = "xxxxxxx";
var API_KEY=apiKey;
var sessionId = "2_MX40NTAyMDgxMn5-xxxxxxxxxxxxxxxxxxxxHBXZEZoWHN-fg";
var token = "T1==cGFydG5lcl9pZD00NTAyMDgxMiZzaWc9ZDNiYjYyZGE2NTBkYmUzMTUyNGNjNDZjYzAzY2NjZWRhZGY3NTEyZjpyb2xlPW1vZGVyYXRvciZzZXNzaW9uX2lkPTJfTVg0xxxxxxxxxxxxxxxxxxxxxxxxBNM1JsYlRCUFdXWkhSSEJYWkVab1dITi1mZyZjcmVhdGVfdGltZT0xNDEzMjAwMjIxJm5vbmNlPTAuMTk1MzEwNTU0MzY1MjEwNSZleHBpcmVfdGltZT0xNDEzMjg0MzY5";
// Initialize session, set up event listeners, and connect
var session;
var connectionCount = 0;
function connect() {
session = TB.initSession(sessionId);
session.addEventListener("sessionConnected", sessionConnectHandler);
session.addEventListener('streamCreated', function(event){
e=event;
console.log(e);
for (var i = 0; i < event.streams.length; i++) {
streams = event.streams;
// Make sure we don't subscribe to ourself
alert("new user connected :)");
if (streams[i].connection.connectionId == session.connection.connectionId) {
return;
}
// Create the div to put the subscriber element in to
var div = document.createElement('div');
div.setAttribute('id', 'stream' + streams[i].streamId);
document.body.appendChild(div);
session.subscribe(streams[i], div.id);
}
});
session.connect(API_KEY, token);
}
function sessionConnectHandler(event) {
var div = document.createElement('div');
div.setAttribute('id', 'publisher');
var publisherContainer = document.getElementById('publisherContainer');
// This example assumes that a publisherContainer div exists
publisherContainer.appendChild(div);
var publisherProperties = {width: 500, height:450};
publisher = TB.initPublisher(API_KEY, 'publisher', publisherProperties);
session.publish(publisher);
}
function disconnect() {
session.disconnect();
}
connect();
</script>
</head>
<body>
<h1>Monkvysa videofeed test!</h1>
<input style="display:block" type="button" id="disconnectBtn" value="Disconnect" onClick="disconnect()">
<table>
<tr>
<td> <div id="publisherContainer"></div></td> <td><div id="myPublisherDiv"></div></td>
</tr>
</table>
</body>
</html>
Thanks in advance
The code looks mostly correct, except you're using an older form of the 'streamCreated' event handler. In the latest version of the API, you no longer need to iterate through the event.streams array, you actually get one invocation of the event handler per stream.
In order to further dig into the problem, would you be able to add a link to a gist containing all the console logs? To make sure the logs are being outputted, you can call OT.setLogLevel(OT.DEBUG); at the beginning of the script.
Lastly, the newer API is greatly simplified and you could save yourself the effort of DOM element creation and iteration. What you have implemented is basically identical to our Hello World sample applications, which you can find in any of our server SDKs, for example here: https://github.com/opentok/opentok-node/blob/61fb4db35334cd30248362e9b10c0bbf5476c802/sample/HelloWorld/public/js/helloworld.js
I need call flash function from javascript. I use flash.external and addCallback to do this. all things work well but when I use FileReference in my flash, function did not open my browser ...
please see below describtion:
I call my function in javascript with this code:
<input type="button" value="Browse" onclick="sendToFlash('Hello World! from HTML');" />
you can see all my HTML as below:
<html>
<head>
<title>Upload test</title>
</head>
<script>
function hello (size) {
alert ("size hast: " + size);
}
function sendToFlash(val){
var flash = getFlashObject();
flash.new_browser(val);
}
var flash_ID = "Movie2";
var flash_Obj = null;
function getFlashObject(){
if (flash_Obj == null){
var flashObj;
if (navigator.appName.indexOf( "Microsoft" ) != -1){
flashObj = window[flash_ID];
}
else{
flashObj = window.document[flash_ID];
}
flash_Obj = flashObj;
}
return flash_Obj;
}
</script>
<body>
<center>
<embed width="560" height="410" type="application/x-shockwave-flash"
flashvars="sampleVars=loading vars from HTML"
salign="" allowscriptaccess="sameDomain" allowfullscreen="false" menu="true" name="Movie2"
bgcolor="#ffffff" devicefont="false" wmode="window" scale="showall" loop="true" play="true"
pluginspage="http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"
quality="high" src="Movie2.swf">
</center>
<input type="button" value="Browse" onclick="sendToFlash('Hello World! from HTML');" />
</body>
</html>
when I click Browse in html page, javascript call sendToFlash function and SendToFlash function send my string (Hello World! from HTML) to flash.
in flash I get this string with below code:
resultsTxtField.text = "";
uploadButton.onPress = function () {
return browse_file("Hello World! from Flash");
}
import flash.external.*;
ExternalInterface.addCallback("new_browser", this, browse_file);
function browse_file (my_test_val) {
_root.resultsTxtField.text = "val: " + my_test_val;
import flash.net.FileReference;
var fileTypes:Array = new Array();
var imageTypes:Object = new Object();
imageTypes.description = "Images (*.jpg, *.jpeg, *.gif, *.png)";
imageTypes.extension = "*.jpg; *.jpeg; *.gif; *.png";
fileTypes.push(imageTypes);
var fileListener:Object = new Object();
var btnListener:Object = new Object();
var fileRef:FileReference = new FileReference();
fileRef.addListener(fileListener);
fileRef.browse(fileTypes);
fileListener.onCancel = function(file:FileReference):Void
{
_root.resultsTxtField.text += "File Upload Cancelled\n";
}
fileListener.onSelect = function(file:FileReference):Void
{
_root.resultsTxtField.text += "File Selected: " + file.name + " file size: "+ file.size + " file type: " + file.type;
getURL("javascript:hello("+file.size+");");
}
}
I have only one Scene and this code is on root of this Scene. and I have one movie clip named uploadButton and has only a rectangle that work as button in this sample.
when you click on rectangle browse_file("Hello World! from Flash"); called and a browser open that you can select a photo to upload.
when you click on browse in html same process must do but as you see variable send to function but browser to select a photo did not open any more.
I try several ways. for example I set new function to open only picture browser or set new Scene or use gotoAndPlay and more but there is another problem.
you can download my source from below link:
http://www.4shared.com/zip/YTB8uJKE/flash_uploader.html
note that javascript onclick="sendToFlash('Hello World! from HTML');" don't work in direct opening. you must open it in localhost.
I'll be so so happy for any clue.
thanks so much
Reza Amya
You can't programmatically call browse(), it has to be from a mouse click inside Flash: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#browse()
In Flash Player 10 and Flash Player 9 Update 5, you can only call
this method successfully in response to a user event (for example, in
an event handler for a mouse click or keypress event). Otherwise,
calling this method results in Flash Player throwing an Error
exception.
after a day reading I know that it is impossible for security reasons.
then you can't open file reference with addCallback javascript code any way. for more information read fileReference browse from js, simulate keypress in flash workaround
Thanks again
Reza Amya