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前置拍照功能实现(复制可用,亲测有效)

参考博客:Vue 使用 navigator.mediaDevices.getUserMedia 调用本地摄像头实现录像以及拍照功能_八了个戒的博客-CSDN博客_navigator.mediadevices.getusermedia

<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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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的主要内容,如果未能解决你的问题,请参考以下文章

怎么用html5或js调用手机的摄像头拍照上传以及调用

html5移动端页面上调用手机摄像头扫描二维码并获取二维码信息代码?

移动端如何通过文件表单调用前置摄像头(IOS和安卓都能用)

安卓系统手机怎么装uvc?

html5或者JS怎样调用手机摄像头或者相册?

html5或者JS怎样调用手机摄像头或者相册