精华内容
下载资源
问答
  • 关于视频捕捉、录制、切换摄像头在上一篇博客有详细的讲解(https://blog.csdn.net/s12117719679/article/details/100513400), 这里就不做过多解析 聚焦的关键代码如下: 点击手势,根据点击的位置转换成相机...

    github下载链接:https://github.com/SSYSSK/camera2

     

    关于视频捕捉、录制、切换摄像头在上一篇博客有详细的讲解(https://blog.csdn.net/s12117719679/article/details/100513400),

    这里就不做过多解析

     

    聚焦的关键代码如下:

    点击手势,根据点击的位置转换成相机的聚焦点坐标

    -(void)handleSingleTap:(UIGestureRecognizer *)recognizer {
        CGPoint point = [recognizer locationInView:self];
        [self runBoxAnimationOnView:self.focusBox point:point];
        if(self.delegate){
            [self.delegate tappedToFocusAtPoint:point];
        }
    }

     

    相机聚焦实现

    -(void)tappedToFocusAtPoint:(CGPoint)point {
        //[self.activeCamera isFocusPointOfInterestSupported] 是否支持对焦 iPhone6以上才支持
        //[self.activeCamera isFocusPointOfInterestSupported] 是否支持自动对焦模式
        NSLog(@"对焦%f",point.x);
        NSLog(@"对焦%f",point.y);
        if ([self.activeCamera isFocusPointOfInterestSupported] && [self.activeCamera isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
            // 因为设备有多个,所以需要锁定
            if([self.activeCamera lockForConfiguration:nil]){
              
                // 设置聚焦位置
                self.activeCamera.focusPointOfInterest = point;
                // 设置对焦模式
                self.activeCamera.focusMode = AVCaptureFocusModeAutoFocus;
                
                // 释放锁
                [self.activeCamera unlockForConfiguration];
            }
        }
    }

    对焦的模式选择:

    AVCaptureFocusModeLocked 关闭对焦

    AVCaptureFocusModeAutoFocus 自动对焦

    AVCaptureFocusModeContinuousAutoFocus 自动连续对焦

    展开全文
  • api 添加摄像头视频流 根据新增视频流自动发起流转换,并转发到http 服务端口 根据视频流,获取当前快照 服务端录制保存 web前段查看视频 服务端代码 websocket服务 http转换流接收服务 web api接口服务 var fs =...
    Html5 <video>并不支持rtsp协议,记录的是通过ffmpeg来实现,web前段用的是canvas画布来显示。
    

    ffmpeg 安装

    ffmpeg 安装和常见问题

    demo git

    camera-demo

    功能清单

    • api 添加摄像头视频流
    • 根据新增视频流自动发起流转换,并转发到http 服务端口
    • 根据视频流,获取当前快照
    • 服务端录制保存
    • web前段查看视频

    服务端代码

    • websocket服务
    • http转换流接收服务
    • web api接口服务
    //websocket-relay.js
    
    var fs = require('fs'),
      http = require('http'),
      WebSocket = require('ws');
    
    if (process.argv.length < 3) {
      console.log(
        'Usage: \n' +
        'node websocket-relay.js <secret> [<stream-port> <websocket-port>]'
      );
      process.exit();
    }
    
    var STREAM_SECRET = process.argv[2],
      STREAM_PORT = process.argv[3] || 8081,
      WEBSOCKET_PORT = process.argv[4] || 8082,
      HTTP_PORT = process.argv[5] || 8083,
      RECORD_STREAM = false;
    
    // Websocket Server
    var socketServer = new WebSocket.Server({port: WEBSOCKET_PORT, perMessageDeflate: false});
    socketServer.connectionCount = 0;
    socketServer.on('connection', function (socket, upgradeReq) {
    
      var params = upgradeReq.url.substr(1).split('/');
      if (!params || params.length != 1) {
        console.log("deviceId param was loss");
        response.end();
      }
      socket.deviceId = params[0];
      socketServer.connectionCount++;
      console.log(
        'New WebSocket Connection: ',
        (upgradeReq || socket.upgradeReq).socket.remoteAddress,
        (upgradeReq || socket.upgradeReq).headers['user-agent'],
        '(' + socketServer.connectionCount + ' total)'
      );
      socket.on('close', function (code, message) {
        socketServer.connectionCount--;
        console.log(
          'Disconnected WebSocket (' + socketServer.connectionCount + ' total)'
        );
      });
      socketServer.broadcast("fda")
    });
    socketServer.broadcast = function (deviceId, data) {
      socketServer.clients.forEach(function each(client) {
        if (client.deviceId && client.deviceId == deviceId) {
          if (client.readyState === WebSocket.OPEN) {
            client.send(data);
          }
        }
      });
    };
    
    // HTTP Server to accept incomming MPEG-TS Stream from ffmpeg
    var streamServer = http.createServer(function (request, response) {
      var params = request.url.substr(1).split('/');
    
      if (params[1] !== STREAM_SECRET) {
        console.log(
          'Failed Stream Connection: ' + request.socket.remoteAddress + ':' +
          request.socket.remotePort + ' - wrong secret.'
        );
        response.end();
      }
    
      response.connection.setTimeout(0);
      console.log(
        'Stream Connected: ' +
        request.socket.remoteAddress + ':' +
        request.socket.remotePort
      );
      request.on('data', function (data) {
        socketServer.broadcast(params[0], data);
        if (request.socket.recording) {
          request.socket.recording.write(data);
        }
      });
      request.on('end', function () {
        if (request.socket.recording) {
          request.socket.recording.close();
        }
      });
    
      // Record the stream to a local file?
      if (RECORD_STREAM) {
        var path = 'recordings/' + Date.now() + '.ts';
        request.socket.recording = fs.createWriteStream(path);
      }
    })
    // Keep the socket open for streaming
    streamServer.headersTimeout = 0;
    streamServer.listen(STREAM_PORT);
    
    // HTTP Server to start convert shell
    const express = require('express');
    const bodyParser = require('body-parser');
    const child_process = require('child_process');
    
    const httpServer = express();
    httpServer.use(bodyParser());
    httpServer.use(bodyParser.json());
    httpServer.use(bodyParser.urlencoded({extended: true}));
    
    httpServer.killByProcessName = function (name) {
      var shell = `ps aux | grep "${name}" |grep -v grep| cut -c 9-15 | xargs kill -9`;
      try {
        console.log("exec", shell);
        var result = child_process.execSync(shell, {stdio: 'ignore'});
        console.log("进程已存在", result);
      } catch (e) {
        console.log("进程不存在(假定只有不存在的时候才会报错)")
        return false;
      }
      return true;
    }
    
    httpServer.get('/', function (req, res) {
      res.send('摄像头服务');
    });
    const error_image = "data:image/jpg;base64,默认图片"
    /**
    抓帧
    **/
    httpServer.get('/snapshot', function (req, res) {
      if (!req.query.deviceId || !req.query.streamUrl) {
        res.json({succee: false, msg: "缺少参数"});
        return;
      }
      try {
        var frameShell = `ffmpeg -y -i "${req.query.streamUrl}" -ss 1 -frames:v 1 ./${req.query.deviceId}.jpeg`;
        console.log("snapshot", frameShell);
        child_process.execSync(frameShell, {stdio: 'ignore'});
        let bitmap = fs.readFileSync(`./${req.query.deviceId}.jpeg`);
        let base64str = Buffer.from(bitmap, 'binary').toString('base64');
        res.send("data:image/jpg;base64," + base64str);
        return;
      } catch (e) {
        console.log("在抓帧时获得异常,返回默认", e)
      }
      res.send(error_image);
    });
    httpServer.post('/camera', function (req, res) {
      console.log(req.body)
      if (!req.body.deviceId || !req.body.streamUrl) {
        res.json({succee: false, msg: "缺少参数"});
        return;
      }
      var exist = httpServer.killByProcessName(`http://127.0.0.1:8082/${req.body.deviceId}`);
      var cmd = `ffmpeg -rtsp_transport tcp -i "${req.body.streamUrl}" -f mpegts -b:v 800k -codec:v mpeg1video -codec:a mp2 -s 640x480 -r 32 "http://127.0.0.1:8082/${req.body.deviceId}/123456/640/480/"`;
      try {
        child_process.exec(cmd, function (error, stdout, stderr) {
          if (error) {
            console.log(error)
          }
          console.log("error:" + error);
          console.log("stdout:" + stdout);
          console.log("stderr:" + stderr);
        });
        console.log(`添加[${req.body.deviceId}:${req.body.streamUrl}]成功!`)
      } catch (e) {
        console.log(`添加[${req.body.deviceId}:${req.body.streamUrl}]失败!`, e)
        return res.json({succee: false, msg: "添加失败!"})
      }
      exist ? res.json({succee: true, msg: "已启动脚本!"}) : res.json({succee: true, msg: "已重启脚本!"});
    });
    httpServer.listen(HTTP_PORT);
    
    console.log('Listening for incomming MPEG-TS Stream on http://127.0.0.1:' + STREAM_PORT + '/<secret>');
    console.log('Awaiting WebSocket connections on ws://127.0.0.1:' + WEBSOCKET_PORT + '/');
    console.log('Web Api service on http://127.0.0.1:' + HTTP_PORT + '/');
    

    package.json

     "dependencies": {
        "body-parser": "^1.19.0",
        "child_process": "^1.0.2"
      }
    

    启动服务

    node websocket-relay.js 123456 8082 8084 8087
    

    html源码

    <!DOCTYPE html>
    <html>
    <head>
      <title>JSMpeg Stream Client</title>
      <style type="text/css">
        html, body {
          background-color: #111;
          text-align: center;
        }
      </style>
    </head>
    <body>
    <canvas id="video-canvas"></canvas>
    <script type="text/javascript" src="jsmpeg.min.js"></script>
    <script type="text/javascript">
      var canvas = document.getElementById('video-canvas');
      var url = 'ws://192.168.100.13:8084/deviceId1';
      var player = new JSMpeg.Player(url, {canvas: canvas});
    </script>
    </body>
    </html>
    

    常见问题

    1. 视频延迟:取决于比特率和分别率,越低自然延迟就低。
    2. html 部署,可以直接使用http-server模块部署。
    展开全文
  • 想通过 web 录制视频,并将视频上传到后端要怎么实现呢? 2.整体思路 打开摄像头 :MediaDevices.getUserMedia() 录制:使用 MediaRecorder 内存存储:创建一个 [] 数组,存放字节,再转成 blob 对象。 上传:构建...

    1.背景

    想通过 web 录制视频,并将视频上传到后端要怎么实现呢?

    2.整体思路

    • 打开摄像头 :MediaDevices.getUserMedia()
    • 录制:使用 MediaRecorder
    • 内存存储:创建一个 [] 数组,存放字节,再转成 blob 对象。
    • 上传:构建file,再到 formData,使用ajax发起HTTP 请求

    3.实现方式

    获得摄像头设备

    MediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据。

    **MediaDevices.getUserMedia()** 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。

    在用户通过提示允许的情况下,打开系统上的相机或屏幕共享和/或麦克风,并提供 MediaStream 包含视频轨道和/或音频轨道的输入。

    MediaStream 接口是一个媒体内容的流.。一个流包含几个轨道,比如视频和音频轨道。

    录制

    MediaRecorder() 构造函数会创建一个对指定的 MediaStream 进行录制的 MediaRecorder 对象

    var mediaRecorder = new MediaRecorder(stream[, options]);

    ...
    
    
    if (navigator.mediaDevices.getUserMedia) {
      var constraints = { audio: true, video: true };
      var chunks = [];
    
      var onSuccess = function(stream) {
        var options = {
          audioBitsPerSecond : 128000,
          videoBitsPerSecond : 2500000,
          mimeType : 'video/mp4'
        }
        var mediaRecorder = new MediaRecorder(stream,options);
        m = mediaRecorder;
    
    ...

    获得录制过程中的 数据

    MediaRecorder.ondataavailable 调用它用来处理 dataavailable 事件, 该事件可用于获取录制的媒体资源 (在事件的 data 属性中会提供一个可用的 Blob 对象.)

    //  当停止录像以后的回调函数
          _mediaRecorder.ondataavailable = function (data) {
              console.log("# 产生录制数据...");
              console.log(data);
              console.log("# ondataavailable, size = " + parseInt(data.size/1024) + "KB");
              _chunks.push(data);
          };
          _mediaRecorder.onstop = function(e) {
              console.log("# 录制终止 ...");
              const fullBlob = new Blob(_chunks);
              const blobURL = window.URL.createObjectURL(fullBlob);
              console.log("blob is ?, size="+parseInt(fullBlob.size/1024)+"KB. "); console.log(fullBlob);
              console.log("blobURL =" + blobURL);
              //saveFile(blobURL);
              uploadFile(fullBlob);
            }

    从 blob 转成 file

    方法: var myFile = new File(bits, name[, options]);
    参数说明:
    bits: 一个包含ArrayBuffer,ArrayBufferView,Blob,或者 DOMString 对象的 Array — 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。
    name: USVString,表示文件名称,或者文件路径。

    示例:

    var file = new File(["foo"], "foo.txt", {
      type: "text/plain",
    });

    保存文件 到本地文件

    生成一个 A 标签,赋值 href 和 download 属性即可。

    // 保存文件(产生下载的效果)
        let saveFile = function(blob){
          const link = document.createElement('a');
          link.style.display = 'none';
          link.href = blob;
          link.download = 'media_.mp4';
          document.body.appendChild(link);
          link.click();
          link.remove();
        }

    上传到后端服务

    • 创建file对象: file = new File([blob], "media_.mp4");
    • 构建成 fromData: var formData = new FormData();
    • 再 Ajax 上传即可。
    let uploadFile = function(blob){
          var file = new File([blob], "media_.mp4");
          var formData = new FormData();
          formData.append('file', file);
          console.log(formData);
          console.log("# 准备上传, fileName="+file.name +", size="+ parseInt(file.size/1024)+" KB");
          let $output = $("#output");
          $.ajax({
              type:"POST",
              url: "/uploadvideo",
              data: formData,
              processData: false,
              contentType: false,
              success:function (){
                 $output.prepend("上传视频成功!");
               },
              error : function() {
                $output.prepend("上传视频失败!");
              }
           });
        }

    判断其 MIME 格式能否被客户端录制

    MediaRecorder.isTypeSupported()方法会判断其 MIME 格式能否被客户端录制。

    var canRecord = MediaRecorder.isTypeSupported(mimeType)

    "video/webm",
                 "audio/webm",
                 "video/webm\;codecs=vp8",
                 "video/webm\;codecs=daala",
                 "video/webm\;codecs=h264",
                 "audio/webm\;codecs=opus",
                 "video/mpeg"

    关闭视频流

    遍历 _mediaStream ,终止所有的 track 即可。

    // 关闭流
        var closeMediaStream = function(){
          if(!_mediaStream) return;
          console.log("# 关闭数据流");
          _mediaStream.getTracks().forEach(function (track) {
            track.stop();
          });
          _mediaStream = undefined;
          _mediaRecorder = undefined;
        }

    后端代码:接收视频文件

    创建一个 controller ,接收 MultipartFile 参数,保存文件流即可。

    /**
     * @description:
     * @author: zhangyunfei
     * @date: 2021/4/25 19:22
     */
    @RestController
    @RequestMapping()
    public class UploadFileController {
        public static final String IMAGE_STORE_DIR = "/Users/zhangyunfei/git/demo/video2/public";
        private static final String TAG = UploadFileController.class.getSimpleName();
    
    
        @PostMapping(value = "/uploadvideo", name = "接收上传文件")
        public String uploadVideo(@RequestParam("file") MultipartFile uploadFile) {
            String name = uploadFile.getOriginalFilename();
            String size = String.format("%.2f MB", uploadFile.getSize() / 1024f / 1024f);
            System.out.println(String.format("# name=%s, size=%s", name, size));
            saveFile(uploadFile);
            return "ok";
        }
    
        private void saveFile(MultipartFile uploadFile) {
            try {
                String fileName = UUID.randomUUID().toString() + ".mp4";
                File path = new File(IMAGE_STORE_DIR, fileName);
                uploadFile.transferTo(path);
                LogUtil.d(TAG, "## 保存文件成功,路径=%s", path.getPath());
            } catch (IOException e) {
                e.printStackTrace();
                LogUtil.d(TAG, "## 保存文件失败,%s", e);
            }
        }
    
    }

    后端设置:修改最大上传文件大小和请求大小。

    需要修改最大上传文件大小和请求大小,不然默认的 1MB是不够用的。

    也很简单,修改配置文件即可。

    spring:
        servlet:
            multipart:
                max-file-size: 50MB  #单个数据大小
                max-request-size: 100MB #总数据大小

    4.我的示例

    示例指南见:https://www.jianshu.com/p/052a7fecc358
    代码在 github: https://github.com/vir56k/demo/tree/master/video2

    5.参考

    Web API 接口参考https://developer.mozilla.org/zh-CN/docs/Web/API

    参考视频示例:https://www.jianshu.com/p/052a7fecc358https://wendychengc.github.io/media-recorder-video-canvas/videocanvas.html

    https://cloud.tencent.com/developer/article/1366886

    https://segmentfault.com/q/1010000011489899

    http://www.zuidaima.com/blog/3819727543307264.htm

    展开全文
  • 今天在查CCF题目的时候看到有个老哥问我,MediaRecorder在录制过程,能否改变在构造函数引入的流。 这个我还真没有试过,之前写的H5直播虽然我一直声称在手机端可以选择前置或后置摄像头,但实际上一旦选择了就...

    今天有个老哥问我,MediaRecorder在录制过程中,能否改变在构造函数中引入的流。

    这个我还真没有试过,之前写的H5直播虽然我一直声称在手机端可以选择前置或后置摄像头,但实际上一旦选择了就没法更改了......其实我确实有考虑过解决这个问题,但当时实在是太累(lan)了,最后答辩就给糊弄过去了,难得今天不想干正事,试试。

     

    过程

    首先直接MediaRecorder.stream=new_stream的想法可以省省,不用猜就知道这里面的stream肯定是个只读属性

    一般遇到这种问题我都先去外网上看看有没有什么高见,堆栈溢出上看见这么一个:https://stackoverflow.com/questions/57838283/is-it-possible-to-change-mediarecorders-stream?r=SearchResults

    老哥上来就说做不到,emmmmmmmm....但是提问的人问的是track,我觉得可能跟我想的是不一样的,动手试试吧。既然没法修改stream,我直接new一个新的MediaRecorder替换原来的不可以吗?

    记得之前看示例的时候有一个是教如何切换使用的设备的(Choose camera, microphone and speaker),里面演示了如何切换设备以及切换后的效果,怎么实现的并不重要,没那么多时间去细细品味,扒下来代码,找到自己以前写的MediaRecorder的代码,拿出作为代码人的骄傲,开始写一个缝合怪。写到饭点,看完API的顺道去看了一下自己的Chrome版本,放那里没管吃饭去了,回来一看Chrome界面不对,自己给我更新了……更新完之后发现最早写的MediaRecorder代码不管用了我日,好在还有另一份使用blob的还可以,得重新写自己的缝合怪了

    写完之后大概是这样的:

    上面的video标签显示的是当前调用的摄像头的实时图像,下面的video标签播放的是使用MediaRecorder录制的,
    点击Record按钮MediaRecorder就会开始工作,stop为结束录制,printstate是测试用的,在控制台打印状态信息

    在魔改原来sample代码的过程中,我在设备下拉菜单的事件触发函数里加上了代码,在设备改变之后,new一个新的MediaRecorder替代原来的,将新的设备的stream作为MediaRecorder的参数传入,将其绑定起来。

    function gotStream(stream) {
            //这个函数跟在getUserMedia之后,参数中的stream就是新设备的stream
        
            window.stream = stream; // make stream available to console
            videoElement.srcObject = stream;//在上面的video标签中显示
      
            //缝合怪
            //初始化MediaRecorder
    		var record_options = {
    			audioBitsPerSecond:128000,
    			videoBitsPerSecond:2500000,
    			mimeType : mimeType_for_test
    		}
    
    		//创建MediaRecorder
            //注意MediaRecorder已经在js文件的开头声明
    		mediaRecorder=new MediaRecorder(stream,record_options);
    
    		//当录制的数据可用时
    		mediaRecorder.ondataavailable=function(e) {
    			//console.log(e.data);
    			if(e.data.size>0){		
    				var reader = new FileReader();
    				var arr = [];
    				arr.push(e.data);
    				var blob = new Blob(arr,{'type':mimeType_for_test});
    				reader.readAsArrayBuffer(e.data);
    				
    				reader.onloadend = function(e){
    					sourcebuffer.appendBuffer(reader.result);
    					sourcebuffer.addEventListener('updateend',function(){
    					});
    				}
    			}
    		}
    	
    	//mediaRecorder.start(timecell);
    	mediaRecorder.onstart = function(e) {
    	  console.log('Record onstart');
        }
        mediaRecorder.onstop = function(e) {
    	  console.log('Record onstop');
        }
    	//缝合怪的尾巴
    
      return navigator.mediaDevices.enumerateDevices();//用于后面的函数更新设备标签
    }

    诶嘿嘿,不愧是我,轻易地就做到了一般人做不到的事情

    但是在实际运行起来就遇到了很操蛋的问题

    MediaRecorder无法start

    在录制过程中直接用new MediaRecorder替换原来的会导致下面的播放卡住,即便sourcebuffer一直在不停地append但是无法播放,于是我考虑是不是在改变stream之前将录制停止,new完之后再重新开始录制。当我这么做了之后遇到了下面的问题:

    于是我分阶段在控制台中打印MediaRecorder,检查它的状态

    正常录制过程中
    刚刚用new MediaRecorder切换完stream后
    切换完过了一段时间之后

    对比上面三个可以发现,在刚刚切换完stream之后,MediaRecorder下的stream属性下的active属性值是false,当一段时间过后才会变为true,当其为false时试图调用MediaRecorder.start()就会导致报错。我看到了active下面还有个onactive,诶嘿嘿这个好东西啊,这不就是active变为true时的触发事件吗,赶紧绑定函数,变为true时就启动我的MediaRecorder!

    过了好久好久

    “onactive还没有被实现.......”,我靠了这帮人为什么这么喜欢挖坑不填啊。被逼无奈,在切换stream后等待,当stream.active的值为true时再start我的MediaRecorder。(这里又被自己蠢到了,代码苦手最近C++写太多了,我直接写了个while(1)里面写了个判断跳出循环,然后直接把页面给卡死了....蠢到自己不自知以为是页面开太多了头铁地又试了一次...)写个setTimeout完事

    function tryRestartRecorder(){
    	if(mediaRecorder.stream.active){
            try{
    			mediaRecorder.start(timecell);
    		}catch(e){}
    	}else{
    		setTimeout(tryRestartRecorder,100);
    	}
    }
    
    
    function changestream(){
    	try{
    		mediaRecorder.stop();//防止MediaRecorder还没有初始化
    	}catch(e){}
    	start();//切换stream的函数
    	setTimeout(tryRestartRecorder(),100);
    }

    这样就成了,切换音频输入输出同理。

     

    navigator.mediaDevices.enumerateDevices()不显示设备名称

    收尾的时候发现不显示设备名称

    这个博客里面提到需要部署到服务器上去才能够获取到设备名称,可能是因为不是https连接导致navigator.mediaDevices.enumerateDevices()函数没有权限

     

    Demo

    demo地址

    展开全文
  • 目标:打开摄像头并捕获照片播放本地视频,录制视频OpenCV函数:cv2.VideoCapture(),cv2.VideoWriter()教程打开摄像头要使用摄像头,需要使用cv2.VideoCapture(0)创建VideoCapture对象,参数:0指的是摄像头的编号。...
  • 有人会回答吗…
  • 需求: 在vue项目使用摄像头拍摄照片传递后台,进行AI对比,如果对比成功可以进行下一步操作,如果失败则进行拦截
  • (PS:目前相册选择照片和调用摄像头拍照已经实现了压缩,录制小视频暂未实现,哪位大佬有好的建议,请指教!) 实现步骤: 1.新建一个AndroidStudio项目。绘制MainActivity的xml文件,这里为了直观,我们放上几个...
  • IOS-摄像头采集-录制

    千次阅读 2018-09-11 11:29:02
    iOS视频录制功能预研  丨n水瓶座菜虫灬 关注 2017.10.13 14:12* 字数 3394 阅读 159评论 0喜欢 4 ...特点: 可用于从相簿选取照片、拍照、录制视频,使用简便,提供的配置有录制视频的质量、前后...
  • 客户端——录制视频之“行”在PC端调用摄像头录制视频,传给后端生成链接。实现步骤:上代码(代码及属性介绍): 在PC端调用摄像头录制视频,传给后端生成链接。 说说最近做的这个功能的需求,就是简单的在PC端调起...
  • 之前写过一篇文章,实时展示摄像头内容 有提到过一种实时展示摄像头内容的方式:集成ffmpeg相关的代码,并转换成图片传给web界面进行相应的展示,现补充下具体的实现。 ffmpeg简介 ffmpeg是一套可以用来记录、转换...
  • 使用MediaRecorder + SurfaceView录制视频,切换为前置摄像头: try { Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); int numberOfCameras = Camera.getNumberOfCameras(); ...
  • 基于VFW实现摄像头录制并保存视频文件 本文介绍了通过使用Windows提供的VFW(Microsoft Video for Windows)实现摄像头的开启和视频文件的保存。 主要接口函数介绍 1.capCreateCaptureWindow函数:创建一个捕获窗口...
  • 每秒10帧、20秒开始、大小为150*100像素,录制视频: ffmpeg.exe -i rtmp://s2pchzxmtymn2k.cloudfront.net/cfx/st/mp4:sintel.mp4 -r 5 -ss 20 -s 150*100 c:\\video.flv 截图,帧率为一,大小220*220,5...
  • 摄像头

    2016-12-24 16:50:19
    摄像头摄像,拍照,视频接口类型。 串口,并口,USB,IEEE1394 图像传感器。 CCD,CMOS 镜 头。 塑胶,玻璃 类 型。 数字,模拟分辨率 分辨率是用于度量位图图像内数据量多少的一个参数,通常表示成dpi(dot ...
  • import cv2import numpy as npimport oscap = cv2.VideoCapture(1)#v4l2-ctl --list-devices 查看设备号,非正常中断时,设备号会变,??????????...后续解答fourcc=0x7634706dout = cv2.VideoWriter('1.mp4',...
  • /** * 停止录制视频 * */ private View.OnClickListener stopVideo = new View.OnClickListener() { @Override public void onClick(View v) { ivStart.setVisibility(View.VISIBLE); ivStop.setVisibility(View....
  • 前几天编译了个mplayer 1.0rc2,我几乎就找不到播不了的音视频了,正开心,发现mencoder好像不能转换音频, 提示说非要有视频不可,狂晕,什么玩意儿~ 反正现在也在乎多折腾一个了,再把最新的ffmpeg装上吧: ...
  • 大佬们,今日小弟在实现安卓前置摄像头录制视频时,发现将录制后的视频保存后在本地播放时呈现镜像翻转,具体效果如下: ![图片说明](https://img-ask.csdn.net/upload/201906/25/1561451270_561379.png) 我使用...
  • python几个获取时间的函数: time.time() 获得以秒为单位的浮点时间 time.ctime()获得人能理解直观时间 time.localtime()获取当前时区的当前时间 若需要了解各种类型时间的数值转换百度即可。 2.获取编码格式...
  • 前提: ... 再者,推流你得有个流媒体服务,个人测试用小水管:rtmp://eguid.cc:1935/rtmp/test(小水管,请尽量...一、摄像头信息采集和录制推流 摄像头名称要通过这个命令拿到,然后替换掉下面的“Integrated Came...
  • 本文主要介绍使用 WVP+ZLMediaKit+MediaServerUI 实现通过 GB28181 进行海康、大华、宇视等品牌的 IPC、NVR 、DVR 接入,完成摄像头监控播放,控制,录制 准备工作 服务运行环境,Linux / OS X / Windows 均可,但...
  • 在嵌入式Linux系统使用摄像头

    万次阅读 2016-02-20 00:12:54
    本文主要基于ARM嵌入式模块系统展示在嵌入式Linux使用摄像头示例,所采用的模块为Toradex VF61,是一款性价比极高但不包含硬件视频编解码加速的模块,核心处理器为NXP/Freescale Vybrid,Cortex-A5和M4异构双核...
  • Android切换前后置摄像头录制视频

    千次阅读 2014-07-13 14:20:52
     * 是否正在录制true录制中 false未录制    */     private   boolean  isRecord= false ;      public   boolean  isCameraBack= true ;      private  ImageView recordIv;...
  • JAVA-WVP+ZLMediaKit+MediaServerUI实现摄像头 GB28181推流播放录制整个视频请求的流程图一.流程图二. 通信流程图三.流程概括图四. gb28181 在线文档准备工作运行流媒体服务 ZLMediaKit (`windows版本`)配置config...
  • import cv2import sysimport timedt = "2019-01-23 15:29:00"#转换成时间数组timeArray = time.strptime(dt, "%Y-%m-%d %H:%M:%S")#转换成时间戳timestamp = time.mktime(timeArray)print(timeArray)print(timestamp...
  • AVURLAsset *avAsset = [ AVURLAsset URLAssetWithURL:[ NSURL fileURLWithPath:path] options: nil ]; ... *compatiblePresets = [ ...@"转换成功" ); break ; default : break ; } }]; }
  •   AVURLAsset *avAsset = [ AVURLAsset URLAssetWithURL:[ NSURL fileURLWithPath:path] ...@"转换成功"); break; default: break; } }]; } 转载于:https://www.cnblogs.com/fantasy940155655/p/9034887.html
  • 前端使用navigator.mediaDevices.getUserMedia和window.MediaRecorder实现调用摄像头录制视屏 一、navigator.mediaDevices.getUserMedia MediaDevices.getUserMedia()会提示用户给予使用媒体输入的许可,媒体输入会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,595
精华内容 2,238
关键字:

录制中转换摄像头