jhuckaby / webcamjs

HTML5 Webcam Image Capture Library with Flash Fallback
MIT License
2.5k stars 1.11k forks source link

[Modules] swf expects global Webcam object for hooks #63

Open positlabs opened 9 years ago

positlabs commented 9 years ago

Using webcamjs with a module system (commonjs) is currently incompatible with the webcam.swf callback hooks. I'm guessing that it's expecting there to be a global Webcam object with a flashNotify method.

To solve this, we could define a unique method name on the window, and pass the name to the swf when it is created.

window.__webcamjs-flash-notify_{uuid} = function(type, msg){...}

This would allow easy(er) setup with module systems.

What do you think?

jhuckaby commented 9 years ago

I apologize, but I don't know anything about CommonJS, or how it works. Couldn't you just add a Webcam reference to the window object after loading the module? It seems strange to have to do something like window.__webcamjs-flash-notify_{uuid} = function(type, msg){...} just for CommonJS.

positlabs commented 9 years ago

AMD modules will have the same issue. If Webcam needs to be global for flash hooks, I think the module wrapper should be removed. Or maybe just assign it to the window regardless of if it's a module or not (not best practice in module-land, though).

I spent a while tracking down why the swf wasn't working for me. It kept saying that it wasn't loaded, even though I could see that it was working. I had to add some console.logs before I realized that the flash hooks weren't being called. It wasn't immediately apparent what the issue was. For now, I have just required webcamjs and assigned it to the window, but I'm sure other users will run into this issue.

jhuckaby commented 9 years ago

Okay, I think I see what you are saying. I'm so sorry this caused an issue for you. I have to admit, I know absolutely nothing about CommonJS, AMD, RequireJS, or any of those module loaders. The module support in this library was coded by someone else and sent to me as a pull request, and I blindly accepted it without understanding the ramifications:

https://github.com/jhuckaby/webcamjs/pull/45

I guess I should remove that wrapper. Sorry! I really need to read up on JS modules and how they work. I am a total n00b at this.

positlabs commented 9 years ago

No worries! Thanks for being so responsive!

myongjailee commented 8 years ago

Hi positlabs, This is #47 and I'm still trying to build webcam.js for two cameras. I want to try your idea. But I'm not able to figure out your suggestion. Could you please share your code if you've tried any: window._webcamjs-flash-notify{uuid} = function(type, msg){...} method? thanks!

positlabs commented 8 years ago

I made a PR for this. It's WAY diverged from the main branch, but you can see my solution here: https://github.com/jhuckaby/webcamjs/pull/66

Another option might be something involving iframes. I think that would work...

myongjailee commented 8 years ago

The solution #66 seems challenging for me to digest yet. I'll give it a try. Thanks a lot.

positlabs commented 8 years ago
  1. You need to make Webcam instantiate-able. It needs to be a function, not an object. Compare... https://github.com/jhuckaby/webcamjs/blob/master/webcam.js#L11 https://github.com/positlabs/webcamjs/blob/module-compat/webcam.js#L11 Method names should be defined on the prototype. https://github.com/positlabs/webcamjs/blob/module-compat/webcam.js#L49
  2. Make a unique name for flash interface method, in order to assign it to the window object. Then pass this unique name in to the swf, via params. The name needs to be unique since we want multiple instances of Webcam. It would be bad if one swf fired callbacks on the wrong instance. https://github.com/positlabs/webcamjs/blob/module-compat/webcam.js#L62-L64 https://github.com/positlabs/webcamjs/blob/module-compat/flash/Webcam.as#L54
  3. ...more? It's been a while since I wrote this, so I don't remember all of the changes offhand.

It's a lot of work, but it doesn't change any of the functionality other than being able to use multiple instances.

I hope this gets you started. Good luck!

myongjailee commented 8 years ago

Your guide above was very helpful. I was able to activate two webcams after trials. I appreciate your helps.

justintoth commented 8 years ago

@myongjailee How were you able to update the .as file and recompile the .swf? I'm struggling because positlab's forked repo is a year old, so doesn't have the latest .swf changes, but it has a change required to support multiple webcam instances.

myongjailee commented 8 years ago

I was able to run two webcams working with a little modification of positlabs source(index.js file). No modification of .as file was made. This is the part to create two webcams.

function createWebcam(args){
    var camParams = args['params'];
    var webcam = new Webcam(camParams);
    // forcing flash to test the uuid flash interface
    webcam.swfURL = camParams['swfURL'];
    webcam.webCamId = camParams['webCamId'];
    // console.log("webcam.webCamId");
    // console.log(webcam.webCamId);
    this.takePhoto = function(fileName){
        webcam.snap( function(data_uri) {
            webcam.upload( data_uri, fileName, function(code, text) {
                console.log(text);
            var imageString = '<img border="0" src="' + data_uri;
                imageString += '" width="320" height="240">';
            $(args['photoDiv']).html(imageString);
            } );
        } );
    }
    webcam.attach( args['camera'] );
};

window.webcam1 = new createWebcam(
    {
        params: {
                webCamId: "myWebcam1",
                swfURL: "./webcam.swf",
                force_flash: true,
                width: 320,
                height: 240,
                dest_width: 1280,
                dest_height: 960,
                image_format: 'jpeg',
                jpeg_quality: 85,
                webcam_movie_embed: "webcam_movie_embed1",
                webcam_movie_obj: "webcam_movie_obj1" },
        camera: "#camera1",
        photoDiv: "#img1"
    }
);

window.webcam2 = new createWebcam(
    {
        params: {
                webCamId: "myWebcam2",
                swfURL: "./webcam.swf",
                force_flash: true,
                width: 320,
                height: 240,
                dest_width: 1280,
                dest_height: 960,
                image_format: 'jpeg',
                jpeg_quality: 85,
                webcam_movie_embed: "webcam_movie_embed2",
                webcam_movie_obj: "webcam_movie_obj2" },
        camera: "#camera2",
        photoDiv: "#img2"
    }
);  

And you need to set the "construct object/embed tag" part, too:

// construct object/embed tag
html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" type="application/x-shockwave-flash" codebase="'+this.protocol+'://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+this.params.width+'" height="'+this.params.height+'" id="' + this.params.webcam_movie_obj + '" align="middle"><param name="wmode" value="opaque" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+this.swfURL+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><embed id="' + this.params.webcam_movie_embed + '" src="'+this.swfURL+'" wmode="opaque" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+this.params.width+'" height="'+this.params.height+'" name="' + this.params.webcam_movie_embed + '" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'"></embed></object>';