Actionscript 3 使用Google Chrome的Flash Player中的空摄像机名称
所以,似乎我们在与谷歌Chrome PPAPI集成的Flash Player中遇到了另一个设备、摄像头和麦克风的问题。许多Flash开发人员都能记住并修复Google Chrome中实现的这个问题。现在,如果你有一些使用相机或麦克风的应用程序,谷歌浏览器用户必须允许访问他们的设备两次:对于Flash Player,以Flash对象为中心的小窗口;对于谷歌浏览器,地址栏下有按钮的灰色面板 直到最近,授予摄像头访问权限的整个过程都是这样的: 应用程序希望将摄像头连接到视频对象或NetStream。 即使未经许可,您也可以获取相机名称并填充一些 使用它们的UI组件。 Flash Player显示带有允许和拒绝按钮的安全面板。 谷歌Chrome展示了它自己的安全面板,所以两个安全面板 同时可见。 用户按下Flash Player安全面板中的允许按钮。 现在,camera.muted属性为false,但camera显示为零 FPS,因为在浏览器中仍然拒绝访问。 用户按下浏览器安全面板中的允许按钮。 赢您可以访问任何地方。 当然,谷歌Chrome的第二个安全面板真的很痛苦。用户只是没有注意到而已。Flash开发人员在应用程序和FAQ页面中通过提示处理了这个问题。但现在我们有另一个大问题 最近,授予摄像头访问权限的过程更改为: 应用程序希望将摄像头连接到视频对象或NetStream 在浏览器中授予访问权限之前,您无法获取相机名称。那里 将仅为空格,camera.name中带有代码32的符号 所有物 Flash Player显示带有允许和拒绝按钮的安全面板。 Google Chrome在获得访问权限之前不会显示其安全面板 在Flash播放器中。 用户按下Flash Player安全面板中的允许按钮。 现在,camera.muted属性为false,但camera显示为零 FPS和没有名称,因为在浏览器中仍然拒绝访问。 谷歌浏览器展示了它自己的安全面板。 用户按浏览器安全面板中的允许按钮此面板 出于某种原因显示了两次。 现在,您可以在任何地方访问,但设备仍然只有 空格而不是实名。 不幸的是,在浏览器中授予访问权限后,AS3将不会更新相机名称。在授予浏览器访问权限之前,Flash Player设置窗口中的相机名称为空事件。所以,现在要在运行于谷歌Chrome的Flash应用程序中获得相机名称而不重新加载是不可能的。用户需要先在浏览器中授予访问权限,然后重新加载应用程序,只有在这之后,我们才能在AS3中获得相机名称。我曾尝试使用flash.media.scanHardware刷新相机名称,但似乎不起作用。 我还创建了一个小示例,并将其发布到网上: 你可以在谷歌浏览器上自己测试。只是别忘了每次都要明确你的选择。您需要从上的列表中删除wonderfl.net条目chrome://settings/contentExceptionsmedia-stream 清除你以前的选择。 我还收到了Opera用户的类似投诉 这是我的密码:Actionscript 3 使用Google Chrome的Flash Player中的空摄像机名称,actionscript-3,flash,google-chrome,camera,Actionscript 3,Flash,Google Chrome,Camera,所以,似乎我们在与谷歌Chrome PPAPI集成的Flash Player中遇到了另一个设备、摄像头和麦克风的问题。许多Flash开发人员都能记住并修复Google Chrome中实现的这个问题。现在,如果你有一些使用相机或麦克风的应用程序,谷歌浏览器用户必须允许访问他们的设备两次:对于Flash Player,以Flash对象为中心的小窗口;对于谷歌浏览器,地址栏下有按钮的灰色面板 直到最近,授予摄像头访问权限的整个过程都是这样的: 应用程序希望将摄像头连接到视频对象或NetStream。
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
import flash.media.scanHardware;
import flash.text.TextField;
import flash.utils.Timer;
public class BrowserPermissionTest extends Sprite
{
private var output:TextField;
private var timer:Timer;
public function BrowserPermissionTest()
{
super();
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
output = new TextField();
output.border = true;
output.multiline = true;
output.wordWrap = true;
output.x = output.y = 10;
addChild(output);
updateView();
stage.addEventListener(Event.RESIZE, stage_resizeHandler);
var i:int;
var numCameras:int = 0;
var numMicrophones:int = 0;
if (Camera.isSupported)
{
var cameraNames:Array = Camera.names;
numCameras = cameraNames ? cameraNames.length : 0;
if (numCameras > 0)
{
log("Cameras:");
for (i = 0; i < numCameras; i++)
{
var cameraName:String = cameraNames[i];
log((i + 1) + ". \"" + cameraName + "\"");
}
}
else
{
log("Camera not found.");
}
}
else
{
log("Camera is not supported.");
}
log("");
if (Microphone.isSupported)
{
var microphoneNames:Array = Microphone.names;
numMicrophones = microphoneNames ? microphoneNames.length : 0;
if (numMicrophones > 0)
{
log("Microphones:");
for (i = 0; i < numMicrophones; i++)
{
var microphoneName:String = microphoneNames[i];
log((i + 1) + ". \"" + microphoneName + "\"");
}
}
else
{
log("Microphone not found.");
}
}
else
{
log("Microphone is not supported.");
}
log("");
if (numCameras > 0 || numMicrophones > 0)
{
if (numCameras > 0)
{
var defaultCamera:Camera = Camera.getCamera();
var video:Video = new Video(1, 1);
addChild(video);
video.attachCamera(defaultCamera);
defaultCamera.muted ? devicesMutedInFlashPlayer() : devicesUnmutedInFlashPlayer();
}
else if (numMicrophones > 0)
{
var defaultMicrophone:Microphone = Microphone.getMicrophone();
defaultMicrophone.setLoopBack(true);
defaultMicrophone.muted ? devicesMutedInFlashPlayer() : devicesUnmutedInFlashPlayer();
}
else
{
log("No devices found for test.");
}
}
}
private function devicesMutedInFlashPlayer():void
{
log("Devices are muted in Flash Player.");
log("Starting permission check timer...");
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, flashPlayerPermissionTimer_timerHandler);
timer.start();
}
private function flashPlayerPermissionTimer_timerHandler(event:TimerEvent):void
{
var defaultCamera:Camera = Camera.getCamera();
if (!isDevicesMutedInFlashPlayer())
{
timer.stop();
timer.removeEventListener(TimerEvent.TIMER, flashPlayerPermissionTimer_timerHandler);
timer = null;
devicesUnmutedInFlashPlayer();
}
}
private function devicesUnmutedInFlashPlayer():void
{
log("Devices are unmuted in Flash Player.");
isDevicesMutedInBrowser() ? devicesMutedInBrowser() : devicesUnmutedInBrowser();
}
private function devicesMutedInBrowser():void
{
log("Devices are muted in browser.");
log("Starting permission check timer...");
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, browserPermissionTimer_timerHandler);
timer.start();
}
private function browserPermissionTimer_timerHandler(event:TimerEvent):void
{
scanHardware();
if (!isDevicesMutedInBrowser())
{
timer.stop();
timer.removeEventListener(TimerEvent.TIMER, browserPermissionTimer_timerHandler);
timer = null;
devicesUnmutedInBrowser();
}
}
private function devicesUnmutedInBrowser():void
{
log("Devices are unmuted in browser.");
}
private function isDevicesMutedInFlashPlayer():Boolean
{
var cameraNames:Array = Camera.names;
var numCameras:int = cameraNames ? cameraNames.length : 0;
if (numCameras > 0)
{
var defaultCamera:Camera = Camera.getCamera();
return defaultCamera.muted;
}
else
{
var microphoneNames:Array = Camera.names;
var numMicrophones:int = microphoneNames ? microphoneNames.length : 0;
if (numMicrophones > 0)
{
var defaultMicrophone:Microphone = Microphone.getMicrophone();
return defaultMicrophone.muted;
}
}
return true;
}
private function isDevicesMutedInBrowser():Boolean
{
var cameraNames:Array = Camera.names;
var numCameras:int = cameraNames.length;
for (var i:int = 0; i < numCameras; i++)
{
var cameraName:String = cameraNames[i];
if (cameraName != " ")
{
return false;
}
}
var microphoneNames:Array = Microphone.names;
var numMicrophones:int = microphoneNames.length;
for (i = 0; i < numMicrophones; i++)
{
var microphoneName:String = microphoneNames[i];
if (microphoneName != " ")
{
return false;
}
}
return true;
}
private function log(text:String):void
{
output.appendText(text + "\n");
}
private function updateView():void
{
output.width = stage.stageWidth - 2 * output.x;
output.height = stage.stageHeight - 2 * output.y;
}
private function stage_resizeHandler(event:Event):void
{
updateView();
}
}
}
所以,我想知道这是一个bug还是Google Chrome团队实现的某种新的安全功能?也许有人已经遇到了这个问题,可以分享更多的信息。
现在,它看起来像是现代浏览器用所有这些功能和丑陋的解决方案扼杀了Flash
附言:你可以在我的留言中发现一些愚蠢的错误。对不起,我的英语不好。我没有检查你的代码,只是说。。谷歌或Chrome从来没有在定制的Flash播放器上做对过。只要在可能的情况下使用官方的Adobe插件,并给出同样的建议。即使是像文本这样简单的东西,特别是对外来字符的编码,也几乎无法使用,但是官方的插件工作得很好。为了避免重新加载相机名称。。如果PPAPI==true,则可以使应用程序在特定函数运行之前不检查任何相机名称。然后,只有当用户在您的U.I中确认,如果他们撒谎,他们就授予浏览器访问权限时,才运行该功能,只需单击“确定”,然后太糟糕了,他们必须重新加载,否则现在您的应用程序可以安全地检查。谢谢VC.One。不幸的是,我不能强迫用户使用官方的Flash播放器,因为他们中的许多人很难深入研究chrome://plugins. 此外,也没有办法强迫Chrome使用NPAPI闪存而不是PPAPI闪存。这将是一个安全问题,因为PPAPI沙箱。至于主浏览器访问检查。。。你看,问题是大多数用户在遇到一两个小问题后就会离开网站,而浏览器的这一点是个问题。但是关于浏览器的整个想法是好的。也许可以先在JavaScript中调用getUserMedia,而不是等待用户选择,然后再检查Flash中的摄像头。经过两次测试,我发现了PPAPI Flash的奇怪行为。该测试是在两个主权财富基金同时工作在同一页上进行的。第一个是要求像一些普通用户一样访问设备 通过调用video.attachCamera应用程序。第二个SWF是由JavaScript循环创建/删除的,以避免出现这种情况:扫描硬件寻找摄像头需要时间。当运行时发现至少一个摄像头时,在播放器实例的生命周期内不会再次扫描硬件。