vue&h5获取手机前置摄像头(安卓&ios),input capture属性和navigator.mediaDevices
Posted 方磊Nine
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue&h5获取手机前置摄像头(安卓&ios),input capture属性和navigator.mediaDevices相关的知识,希望对你有一定的参考价值。
调用前置摄像头 capture="user" 调用后置摄像头capture="environment"或其他只适用于ios
根据官网解释
iOS最遵守遵守html5规范,其次是X5内核,安卓的webview基本忽略了capture。
官方文档:www.w3.org/TR/2018/REC-html-media-capture-20180201/
对于安卓,亲测capture="user"效果是,第一次打开前置摄像无效,默认还是后置,需要你在第一次打开相机后手动翻转摄像头,后面再打开才会默认前置
<input
class="file"
id="uploadFile"
type="file"
name="image"
accept="image/*"//accept="audio/*"录音"video/*"视频时capture只有两种值,
//一种是user 一种是environment
capture="user"
/>
对于安卓用navigator.mediaDevices的getUserMedia
注:!!!必须在https环境下navigator.mediaDevices才生效,在本地调试http环境navigator.mediaDevices为undefined
API文档:MediaDevices.getUserMedia() - Web API 接口参考 | MDN
基础使用(自行封装成方法或放在生命周期,如:vue mounted里可看效果)
// var constraints=audio: true, video width: 1280, height: 720
var constraints=audio: true, video:true//audio:true&false打开&关闭音频 video:true&false打开&关闭视频
// video width: 1280, height: 720 设置1280x720的摄像头分辨率,不需要再设置video:true,设置分辨率时默认true
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream)
/* 使用这个 stream stream */
var video = document.querySelector("video");//自行创建id="video"的video标签作为相机容器
video.srcObject = mediaStream;
video.onloadedmetadata = function (e)
// video.play();打开播放
;
)
.catch(function(err)
/* 处理 error */
);
vue前置拍照功能实现(复制可用,亲测有效)
<template>
<div class="publish">
<video ref="video"></video>
<canvas style="display: none" id="canvasCamera"></canvas>
<div v-if="imgSrc" class="img_bg_camera">
<img :src="imgSrc" class="tx_img" />
</div>
<button @click="OpenCamera">打开摄像头</button>
<button @click="CloseCamera">关闭摄像头</button>
<button @click="setImage">拍照</button>
</div>
</template>
<script>
export default
data()
return
mediaStreamTrack: ,
video_stream: "", // 视频stream
imgSrc: "", // 拍照图片
canvas: null,
context: null,
;
,
mounted()
// 进入页面 自动调用摄像头
this.getCamera();
,
methods:
// 调用打开摄像头功能
getCamera()
// 获取 canvas 画布
this.canvas = document.getElementById("canvasCamera");
this.context = this.canvas.getContext("2d");
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
if (navigator.mediaDevices === undefined)
navigator.mediaDevices = ;
// 正常支持版本
navigator.mediaDevices
.getUserMedia(
video: true,
audio: false,
)
.then((stream) =>
// 摄像头开启成功
this.mediaStreamTrack =
typeof stream.stop === "function" ? stream : stream.getTracks()[0];
this.video_stream = stream;
this.$refs.video.srcObject = stream;
this.$refs.video.play();
)
.catch((err) =>
console.log(err);
);
,
// 拍照 绘制图片
setImage()
// 点击canvas画图
this.context.drawImage(this.$refs.video, 0, 0, 200, 100);
console.log("拍照", this.context.drawImage);
// 获取图片base64链接 canvas
this.canvas = document.getElementById("canvasCamera");
this.canvas.style.display = "block";
console.log(this.canvas, "拍照 image ", this.canvas.style);
const image = this.cancas.toDataURL("image/png");
this.imgSrc = image;
console.log(this.imgSrc, "拍照 image ", image);
// this.$emit("refreshDataList", this.imgSrc);
,
// 打开摄像头
OpenCamera()
console.log("打开摄像头");
this.getCamera();
,
// 关闭摄像头
CloseCamera()
console.log("关闭摄像头");
this.$refs.video.srcObject.getTracks()[0].stop();
,
,
;
</script>
<style scoped>
video
width: 100%;
height: 300px;
canvas
width: 100%;
height: 300px;
button
width: 100px;
height: 40px;
position: relative;
bottom: 0;
left: 0;
background-color: rgb(22, 204, 195);
.img_bg_camera img
width: 300px;
height: 200px;
</style>
h5拍照(无亲测)
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>摄像头拍照</title>
</head>
<body onload='init()'>
<video id="video">
</video>
<div id='operators'>
<button id="capture">拍照</button> <button id="changeCamera">切换摄像头</button>
</div>
<canvas id="canvas" width="480" height="320"></canvas>
<script>
var cameraFront="";
//访问用户媒体设备的兼容方法
function getUserMedia(constraints, success, error)
currentCamera=constraints;
if (navigator.mediaDevices.getUserMedia)
//最新的标准API
navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
else if (navigator.webkitGetUserMedia)
//webkit核心浏览器
navigator.webkitGetUserMedia(constraints,success, error)
else if (navigator.mozGetUserMedia)
//firfox浏览器
navigator.mozGetUserMedia(constraints, success, error);
else if (navigator.getUserMedia)
//旧版API
navigator.getUserMedia(constraints, success, error);
let video = document.getElementById('video');
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
//视频流变量
var localMediaStream;
function success(stream)
//兼容webkit核心浏览器
let CompatibleURL = window.URL || window.webkitURL;
//将视频流设置为video元素的源
console.log(stream);
//video.src = CompatibleURL.createObjectURL(stream);
video.srcObject = stream;
video.play();
localMediaStream=stream;
function error(error)
alert(`访问用户媒体设备失败$error.name, $error.message`);
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia)
//调用用户媒体设备, 访问摄像头 video和audio: video : width: 480, height: 320 使用前置摄像头, 代码如下: video: facingMode: 'user' 后置摄像头, 代码如下: video: facingMode: exact : 'environment'
getUserMedia(audio: true,video: facingMode: exact : 'environment', success, error);
else
alert('不支持访问用户媒体');
document.getElementById('capture').addEventListener('click', function ()
context.drawImage(video, 0, 0, 480, 320);
)
//当前摄像头
var currentCamera;
document.getElementById('changeCamera').addEventListener('click', function ()
//关闭打开的摄像头
localMediaStream.getTracks().forEach(function(track)
track.stop();
);
if(currentCamera.video.facingMode=='user')
getUserMedia(audio: true,video: facingMode: exact : 'environment', success, error);
else
getUserMedia(audio: true,video: facingMode: 'user', success, error);
)
function init()
document.getElementById('operators').style.width=document.getElementById('video').style.width;
document.getElementById('operators').style.textAlign="center";
</script>
</body>
</html>
vue视频录制(无亲测)
<template>
<div class="publish">
<!-- 下载按钮 -->
<a id="downLoadLink" style="display: none;"></a>
<video ref="video"></video>
<!-- 视频录制或暂停 -->
<div @click="recordOrStop">视频录制</div>
</div>
</template>
<script>
export default
data()
return
mediaStreamTrack: , // 退出时关闭摄像头
video_stream: '', // 视频stream
recordedBlobs: [], // 视频音频 blobs
isRecord: false, // 视频是否正在录制
;
,
mounted()
// 进入页面 调用摄像头
this.getCamera();
,
methods:
// 调用打开摄像头功能
getCamera()
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
if (navigator.mediaDevices === undefined)
navigator.mediaDevices = ;
navigator.mediaDevices
.getUserMedia(
video: true,
)
.then((stream) =>
// 摄像头开启成功
this.mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[0];
this.video_stream = stream;
this.$refs.video.srcObject = stream;
this.$refs.video.play();
)
.catch(err =>
console.log(err);
);
,
// 录制或暂停
recordOrStop()
if (this.isRecord)
this.stop();
else
this.record();
,
// 视频录制
record()
console.log('record');
this.isRecord = !this.isRecord;
let mediaRecorder;
let options;
this.recordedBlobs = [];
if (typeof MediaRecorder.isTypeSupported === 'function')
// 根据浏览器来设置编码参数
if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9'))
options =
MimeType: 'video/webm;codecs=h264',
;
else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264'))
options =
MimeType: 'video/webm;codecs=h264',
;
else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8'))
options =
MimeType: 'video/webm;codecs=vp8',
;
mediaRecorder = new MediaRecorder(this.video_stream, options);
else
// console.log('isTypeSupported is not supported, using default codecs for browser');
console.log('当前不支持isTypeSupported,使用浏览器的默认编解码器');
mediaRecorder = new MediaRecorder(this.video_stream);
mediaRecorder.start();
// 视频录制监听事件
mediaRecorder.ondataavailable = e =>
console.log(e);
// 录制的视频数据有效
if (e.data && e.data.size > 0)
this.recordedBlobs.push(e.data);
;
// 停止录像后增加下载视频功能,将视频流转为mp4格式
mediaRecorder.onstop = () =>
const blob = new Blob(this.recordedBlobs, type: 'video/mp4' );
this.recordedBlobs = [];
// 将视频链接转换完可以用于在浏览器上预览的本地视频
const videoUrl = window.URL.createObjectURL(blob);
// 设置下载链接
document.getElementById('downLoadLink').href = videoUrl;
// 设置下载mp4格式视频
document.getElementById('downLoadLink').download = 'media.mp4';
document.getElementById('downLoadLink').innerHTML = 'DownLoad video file';
// 生成随机数字
const rand = Math.floor((Math.random() * 1000000));
// 生成视频名
const name = `video$rand.mp4`;
// setAttribute() 方法添加指定的属性,并为其赋指定的值
document.getElementById('downLoadLink').setAttribute('download', name);
document.getElementById('downLoadLink').setAttribute('name', name);
// 0.5s后自动下载视频
setTimeout(() =>
document.getElementById('downLoadLink').click();
, 500);
;
,
// 停止录制
stop()
this.isRecord = !this.isRecord;
if (!this.$refs.video.srcObject) return;
const stream = this.$refs.video.srcObject;
const tracks = stream.getTracks();
// 关闭摄像头和音频
tracks.forEach(track =>
track.stop();
);
,
,
;
</script>
<style lang="less" scoped>
.publish
color: #fff;
video
width: 100%;
height: 100vh;
div
position: absolute;
left: calc(50% - 80px);
bottom: 0;
height: 40px;
width: 160px;
font-size: 14px;
border-radius: 10px;
line-height: 40px;
background-color: rgb(25, 179, 179);
text-align: center;
</style>
如何在安卓手机中自动拍照?
【中文标题】如何在安卓手机中自动拍照?【英文标题】:How to capture photo automatically in android phone? 【发布时间】:2011-08-29 09:56:52 【问题描述】:我开发了一个安卓应用程序。因为我使用了前置摄像头功能。它工作正常,但我需要自动捕获。即没有单击快门按钮的声音,我想捕获照片代码..
我的相机活动代码是
private Camera openFrontFacingCameraGingerbread()
int cameraCount = 0;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for ( int camIdx = 0; camIdx < cameraCount; camIdx++ )
Camera.getCameraInfo( camIdx, cameraInfo );
if ( cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT )
try
cam = Camera.open( camIdx );
catch (RuntimeException e)
Log.i("Camera failed to open: ",e.getLocalizedMessage());
return cam;
提前谢谢..
【问题讨论】:
【参考方案1】:按照 Android 开发者reference pages 中列出的步骤进行操作。不需要有“快门按钮”。如果您不想在屏幕上显示图像,可以创建一个虚拟 SurfaceHolder,例如
SurfaceView surface = new SurfaceView(context);
cam.setPreviewDisplay(surface.getHolder());
【讨论】:
我想拍摄照片。无需任何点击或任何事件。我的设备固定在一个区域。首先它扫描二维码,然后拍摄人物照片,然后进行下一步操作。用户无能为力。 . 我想要和条形码扫描或二维码扫描一样的结果 也许我不明白你的问题,但这应该只是调用 takePicture() 并传入回调(实现存储/操作图像的逻辑)的问题。【参考方案2】: public int intPicTaken;
// setPreviewCallback on the camera, wait intil intPicTaken increments to 10, then take the picture
cam.setPreviewCallback(prevCallBack);
public Camera.PreviewCallback prevCallBack = new Camera.PreviewCallback()
@Override
public void onPreviewFrame(byte[] data, Camera camera)
intPicTaken++;
try
if(intPicTaken == 10)
doTakePicture();
catch (Exception e)
System.out.println("onPreviewFrame: " + e.toString());
;
public Camera.PictureCallback mPicture = new Camera.PictureCallback()
@Override
public void onPictureTaken(byte[] data, Camera camera)
System.out.println("PictureCallback onPictureTaken");
try
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap picture = BitmapFactory.decodeByteArray(data, 0, data.length, options);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
picture.compress(Bitmap.CompressFormat.JPEG, 100, baos);
baos.close();
System.out.println("PictureCallback onPictureTaken done");
cam.release();
saveFile(picture);
catch (Exception e)
System.out.println("onPictureTaken: " + e.toString());
;
// take the picture
public void doTakePicture()
try
cam.stopPreview();
cam.takePicture(null, null, mPicture, mPicture);
catch(Exception e)
System.out.println("doTakePicture: " + e.toString());
// saving the file to gallery
public void saveFile(Bitmap bitmap)
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaStorageDir = Environment.getExternalStorageDirectory();
if (! mediaStorageDir.exists())
if (! mediaStorageDir.mkdirs())
System.out.println("saveFile: failed to create directory");
return;
try
String saved = MediaStore.Images.Media.insertImage(this.getContentResolver(), bitmap, "title", "description");
Uri sdCardUri = Uri.parse("file://" + Environment.getExternalStorageDirectory());
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, sdCardUri));
System.out.println("file saved");
catch (Exception e)
System.out.println("saveFile: " + e.toString());
e.printStackTrace();
【讨论】:
【参考方案3】:在创建时写入此代码以自动捕获图像
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom__camera_activity);
mCamera = getCameraInstance();
mCameraPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mCameraPreview);
new Handler().postDelayed(new Runnable()
@Override
public void run()
mCamera.takePicture(null, null, mPicture);
, 5500);
【讨论】:
以上是关于vue&h5获取手机前置摄像头(安卓&ios),input capture属性和navigator.mediaDevices的主要内容,如果未能解决你的问题,请参考以下文章