是否可以通过网站控制 phone 上的相机灯?
Is it possible to control the camera light on a phone via a website?
是否可以通过网站在 phone 上控制相机的手电筒?通过 Chrome 或 Firefox 说。我知道可以使用 Android 或 iOS 应用程序,该应用程序由所有手电筒应用程序实现。我知道可以通过 getUserMedia
系列函数来控制相机。如果没有,有谁知道什么时候可以使用?
您可以通过从 VideoStreamTrack 创建 ImageCapture 并设置选项 来使用 MediaStream Image Capture API "fillLightMode" 到 "flash" 或 "torch"。示例:
<video autoplay="true"></video>
<img />
<button onclick="takePhoto()">Take Photo</button>
<script type="text/javascript">
var imageCapture = null;
var deviceConfig = {
video: {
width: 480,
height: 640,
facingMode: "environment", /* may not work, see https://bugs.chromium.org/p/chromium/issues/detail?id=290161 */
deviceId: null
}
};
var imageCaptureConfig = {
fillLightMode: "torch", /* or "flash" */
focusMode: "continuous"
};
// get the available video input devices and choose the one that represents the backside camera
navigator.mediaDevices.enumerateDevices()
/* replacement for not working "facingMode: 'environment'": use filter to get the backside camera with the flash light */
.then(mediaDeviceInfos => mediaDeviceInfos.filter(mediaDeviceInfo => ((mediaDeviceInfo.kind === 'videoinput')/* && mediaDeviceInfo.label.includes("back")*/)))
.then(mediaDeviceInfos => {
console.log("mediaDeviceInfos[0].label: " + mediaDeviceInfos[0].label);
// get the device ID of the backside camera and use it for media stream initialization
deviceConfig.video.deviceId = mediaDeviceInfos[0].deviceId;
navigator.mediaDevices.getUserMedia(deviceConfig)
.then(_gotMedia)
.catch(err => console.error('getUserMedia() failed: ', err));
});
function takePhoto () {
imageCapture.takePhoto()
.then(blob => {
console.log('Photo taken: ' + blob.type + ', ' + blob.size + 'B');
// get URL for blob data and use as source for the image element
const image = document.querySelector('img');
image.src = URL.createObjectURL(blob);
})
.catch(err => console.error('takePhoto() failed: ', err));
}
function _gotMedia (mediastream) {
// use the media stream as source for the video element
const video = document.querySelector('video');
video.srcObject = mediastream;
// create an ImageCapture from the first video track
const track = mediastream.getVideoTracks()[0];
imageCapture = new ImageCapture(track);
// set the image capture options (e.g. flash light, autofocus, ...)
imageCapture.setOptions(imageCaptureConfig)
.catch(err => console.error('setOptions(' + JSON.stringify(imageCaptureConfig) + ') failed: ', err));
}
</script>
注:
- 在撰写本文时,API 仍在开发中,将来可能会发生变化。
- 要在 Chrome 中启用 ImageCapture,标志 "chrome://flags/#enable-experimental-web-platform-features" 必须设置为 "true"
- 要在 Firefox 中启用 ImageCapture,请在 "about:config"[= 中标记 "dom.imagecapture.enabled" 42=] 必须设置为 "true"。 但是 "setOptions" 在撰写本文时不受支持!
另请参阅:
- Mediastream Image Capture 在 GitHub
- NPM 模块ImageCapture polyfill
这里有一点"torch-app"的网站:
编辑1:我也做了一个jsfiddle
//Test browser support
const SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;
if (SUPPORTS_MEDIA_DEVICES) {
//Get the environment camera (usually the second one)
navigator.mediaDevices.enumerateDevices().then(devices => {
const cameras = devices.filter((device) => device.kind === 'videoinput');
if (cameras.length === 0) {
throw 'No camera found on this device.';
}
const camera = cameras[cameras.length - 1];
// Create stream and get video track
navigator.mediaDevices.getUserMedia({
video: {
deviceId: camera.deviceId,
facingMode: ['user', 'environment'],
height: {ideal: 1080},
width: {ideal: 1920}
}
}).then(stream => {
const track = stream.getVideoTracks()[0];
//Create image capture object and get camera capabilities
const imageCapture = new ImageCapture(track)
const photoCapabilities = imageCapture.getPhotoCapabilities().then(() => {
//todo: check if camera has a torch
//let there be light!
const btn = document.querySelector('.switch');
btn.addEventListener('click', function(){
track.applyConstraints({
advanced: [{torch: true}]
});
});
});
});
});
//The light will be on as long the track exists
}
<button class="switch">On / Off</button>
代码深受此启发 repository, this webseries and this blog-post
编辑 2:
这只适用于 Chrome(也许还有 Opera)。它在 iOS、because Chrome cannot access the camera 上的 Chrome 中不起作用。
我暂时无法在 android 上进行测试。我创建了一个带有输出的新 jsfiddle。如果你有 android phone 但它对你不起作用,它可能会告诉你原因:
https://jsfiddle.net/jpa1vwed/
欢迎调试、评论和编辑。
我修正了 Daniel 的回答,现在按钮在 Android 手机上可以正常工作。 IOS 仍然不受支持。
https://jsfiddle.net/nzw5tv1q/
//have a console on mobile
const consoleOutput = document.getElementById("console");
const log = function (msg) {
consoleOutput.innerText = `${consoleOutput.innerText}\n${msg}`;
console.log(msg);
}
//Test browser support
const SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;
if (SUPPORTS_MEDIA_DEVICES) {
//Get the environment camera (usually the second one)
navigator.mediaDevices.enumerateDevices().then(devices => {
const cameras = devices.filter((device) => device.kind === 'videoinput');
if (cameras.length === 0) {
log('No camera found on this device.');
}
// Create stream and get video track
navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'environment',
}
}).then(stream => {
const track = stream.getVideoTracks()[0];
//Create image capture object and get camera capabilities
const imageCapture = new ImageCapture(track)
imageCapture.getPhotoCapabilities().then(capabilities => {
//let there be light!
const btn = document.querySelector('.switch');
const torchSupported = !!capabilities.torch || (
'fillLightMode' in capabilities &&
capabilities.fillLightMode.length != 0 &&
capabilities.fillLightMode != 'none'
);
if (torchSupported) {
let torch = false;
btn.addEventListener('click', function (e) {
try {
track.applyConstraints({
advanced: [{
torch: (torch = !torch)
}]
});
} catch (err) {
log(err);
}
});
} else {
log("No torch found");
}
}).catch(log);
}).catch(log);
}).catch(log);
//The light will be on as long the track exists
}
<button class="switch">On / Off</button>
<h2>
Console output
</h2>
<div id="console">
</div>
这里是处理手电筒的静态class。您可以在 window 加载时调用 flashlightHandler.accessFlashlight()
。然后使用 flashlightHandler.setFlashlightStatus()
方法,将它传递给 true
或 false
,因为你想要手电筒状态。
class flashlightHandler {
static track; //the video track which is used to turn on/off the flashlight
static accessFlashlight() {
//Test browser support
if (!('mediaDevices' in window.navigator)) {
alert("Media Devices not available. Use HTTPS!");
return;
};
//Get the environment camera (usually the second one)
window.navigator.mediaDevices.enumerateDevices().then((devices) => {
const cameras = devices.filter((device) => device.kind === 'videoinput');
if (cameras.length === 0) {
alert("No camera found. If your device has camera available, check permissions.");
return;
};
const camera = cameras[cameras.length - 1];
window.navigator.mediaDevices.getUserMedia({
video: {
deviceId: camera.deviceId
}
}).then((stream) => {
this.track = stream.getVideoTracks()[0];
if (!(this.track.getCapabilities().torch)) {
alert("No torch available.");
};
});
});
}
static setFlashlightStatus(status) {
this.track.applyConstraints({
advanced: [{
torch: status
}]
});
}
}
是否可以通过网站在 phone 上控制相机的手电筒?通过 Chrome 或 Firefox 说。我知道可以使用 Android 或 iOS 应用程序,该应用程序由所有手电筒应用程序实现。我知道可以通过 getUserMedia
系列函数来控制相机。如果没有,有谁知道什么时候可以使用?
您可以通过从 VideoStreamTrack 创建 ImageCapture 并设置选项 来使用 MediaStream Image Capture API "fillLightMode" 到 "flash" 或 "torch"。示例:
<video autoplay="true"></video>
<img />
<button onclick="takePhoto()">Take Photo</button>
<script type="text/javascript">
var imageCapture = null;
var deviceConfig = {
video: {
width: 480,
height: 640,
facingMode: "environment", /* may not work, see https://bugs.chromium.org/p/chromium/issues/detail?id=290161 */
deviceId: null
}
};
var imageCaptureConfig = {
fillLightMode: "torch", /* or "flash" */
focusMode: "continuous"
};
// get the available video input devices and choose the one that represents the backside camera
navigator.mediaDevices.enumerateDevices()
/* replacement for not working "facingMode: 'environment'": use filter to get the backside camera with the flash light */
.then(mediaDeviceInfos => mediaDeviceInfos.filter(mediaDeviceInfo => ((mediaDeviceInfo.kind === 'videoinput')/* && mediaDeviceInfo.label.includes("back")*/)))
.then(mediaDeviceInfos => {
console.log("mediaDeviceInfos[0].label: " + mediaDeviceInfos[0].label);
// get the device ID of the backside camera and use it for media stream initialization
deviceConfig.video.deviceId = mediaDeviceInfos[0].deviceId;
navigator.mediaDevices.getUserMedia(deviceConfig)
.then(_gotMedia)
.catch(err => console.error('getUserMedia() failed: ', err));
});
function takePhoto () {
imageCapture.takePhoto()
.then(blob => {
console.log('Photo taken: ' + blob.type + ', ' + blob.size + 'B');
// get URL for blob data and use as source for the image element
const image = document.querySelector('img');
image.src = URL.createObjectURL(blob);
})
.catch(err => console.error('takePhoto() failed: ', err));
}
function _gotMedia (mediastream) {
// use the media stream as source for the video element
const video = document.querySelector('video');
video.srcObject = mediastream;
// create an ImageCapture from the first video track
const track = mediastream.getVideoTracks()[0];
imageCapture = new ImageCapture(track);
// set the image capture options (e.g. flash light, autofocus, ...)
imageCapture.setOptions(imageCaptureConfig)
.catch(err => console.error('setOptions(' + JSON.stringify(imageCaptureConfig) + ') failed: ', err));
}
</script>
注:
- 在撰写本文时,API 仍在开发中,将来可能会发生变化。
- 要在 Chrome 中启用 ImageCapture,标志 "chrome://flags/#enable-experimental-web-platform-features" 必须设置为 "true"
- 要在 Firefox 中启用 ImageCapture,请在 "about:config"[= 中标记 "dom.imagecapture.enabled" 42=] 必须设置为 "true"。 但是 "setOptions" 在撰写本文时不受支持!
另请参阅:
- Mediastream Image Capture 在 GitHub
- NPM 模块ImageCapture polyfill
这里有一点"torch-app"的网站:
编辑1:我也做了一个jsfiddle
//Test browser support
const SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;
if (SUPPORTS_MEDIA_DEVICES) {
//Get the environment camera (usually the second one)
navigator.mediaDevices.enumerateDevices().then(devices => {
const cameras = devices.filter((device) => device.kind === 'videoinput');
if (cameras.length === 0) {
throw 'No camera found on this device.';
}
const camera = cameras[cameras.length - 1];
// Create stream and get video track
navigator.mediaDevices.getUserMedia({
video: {
deviceId: camera.deviceId,
facingMode: ['user', 'environment'],
height: {ideal: 1080},
width: {ideal: 1920}
}
}).then(stream => {
const track = stream.getVideoTracks()[0];
//Create image capture object and get camera capabilities
const imageCapture = new ImageCapture(track)
const photoCapabilities = imageCapture.getPhotoCapabilities().then(() => {
//todo: check if camera has a torch
//let there be light!
const btn = document.querySelector('.switch');
btn.addEventListener('click', function(){
track.applyConstraints({
advanced: [{torch: true}]
});
});
});
});
});
//The light will be on as long the track exists
}
<button class="switch">On / Off</button>
代码深受此启发 repository, this webseries and this blog-post
编辑 2: 这只适用于 Chrome(也许还有 Opera)。它在 iOS、because Chrome cannot access the camera 上的 Chrome 中不起作用。 我暂时无法在 android 上进行测试。我创建了一个带有输出的新 jsfiddle。如果你有 android phone 但它对你不起作用,它可能会告诉你原因: https://jsfiddle.net/jpa1vwed/
欢迎调试、评论和编辑。
我修正了 Daniel 的回答,现在按钮在 Android 手机上可以正常工作。 IOS 仍然不受支持。
https://jsfiddle.net/nzw5tv1q/
//have a console on mobile
const consoleOutput = document.getElementById("console");
const log = function (msg) {
consoleOutput.innerText = `${consoleOutput.innerText}\n${msg}`;
console.log(msg);
}
//Test browser support
const SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;
if (SUPPORTS_MEDIA_DEVICES) {
//Get the environment camera (usually the second one)
navigator.mediaDevices.enumerateDevices().then(devices => {
const cameras = devices.filter((device) => device.kind === 'videoinput');
if (cameras.length === 0) {
log('No camera found on this device.');
}
// Create stream and get video track
navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'environment',
}
}).then(stream => {
const track = stream.getVideoTracks()[0];
//Create image capture object and get camera capabilities
const imageCapture = new ImageCapture(track)
imageCapture.getPhotoCapabilities().then(capabilities => {
//let there be light!
const btn = document.querySelector('.switch');
const torchSupported = !!capabilities.torch || (
'fillLightMode' in capabilities &&
capabilities.fillLightMode.length != 0 &&
capabilities.fillLightMode != 'none'
);
if (torchSupported) {
let torch = false;
btn.addEventListener('click', function (e) {
try {
track.applyConstraints({
advanced: [{
torch: (torch = !torch)
}]
});
} catch (err) {
log(err);
}
});
} else {
log("No torch found");
}
}).catch(log);
}).catch(log);
}).catch(log);
//The light will be on as long the track exists
}
<button class="switch">On / Off</button>
<h2>
Console output
</h2>
<div id="console">
</div>
这里是处理手电筒的静态class。您可以在 window 加载时调用 flashlightHandler.accessFlashlight()
。然后使用 flashlightHandler.setFlashlightStatus()
方法,将它传递给 true
或 false
,因为你想要手电筒状态。
class flashlightHandler {
static track; //the video track which is used to turn on/off the flashlight
static accessFlashlight() {
//Test browser support
if (!('mediaDevices' in window.navigator)) {
alert("Media Devices not available. Use HTTPS!");
return;
};
//Get the environment camera (usually the second one)
window.navigator.mediaDevices.enumerateDevices().then((devices) => {
const cameras = devices.filter((device) => device.kind === 'videoinput');
if (cameras.length === 0) {
alert("No camera found. If your device has camera available, check permissions.");
return;
};
const camera = cameras[cameras.length - 1];
window.navigator.mediaDevices.getUserMedia({
video: {
deviceId: camera.deviceId
}
}).then((stream) => {
this.track = stream.getVideoTracks()[0];
if (!(this.track.getCapabilities().torch)) {
alert("No torch available.");
};
});
});
}
static setFlashlightStatus(status) {
this.track.applyConstraints({
advanced: [{
torch: status
}]
});
}
}