Acceso a la cámara con HTML5

¡Saludos visitante! si deseas comentar o hacer una pregunta sobre este post por favor dirígete a la nueva dirección en http://variabletecnica.com.ve. La página que estás leyendo dejará de estar disponible el 15/11/2015. Gracias, y disculpa las molestias 🙂 Hasta hace poco la única forma de acceder a la cámara web desde HTML era por medio…


¡Saludos visitante! si deseas comentar o hacer una pregunta sobre este post por favor dirígete a la nueva dirección en http://variabletecnica.com.ve. La página que estás leyendo dejará de estar disponible el 15/11/2015. Gracias, y disculpa las molestias 🙂

Hasta hace poco la única forma de acceder a la cámara web desde HTML era por medio de flash o instalando algún plugin específico al navegador. Recientemente, gracias a los esfuerzos de los miembros de la W3C, ahora contamos con nuevas etiquetas HTML5 que definen un mecanismo estándar para hacer tareas complejas como esta de forma simple. La influencia de la W3C en la estandarización de tecnologías web poco a poco a logrado que el diseño y la programación web sea más fácil para nosotros y accesible para los usuarios.

Primero hablemos un poco sobre videos: HTML5 define la etiqueta video que nos permite cargar un video, del mismo modo que la etiqueta img nos permite ver una imagen en HTML. Por si misma, la etiqueta video es suficientemente versátil para mostrar un video (en navegadores con soporte HTML5):

<!-- Etiqueta básica -->
<video src="PinturaSecandose.mp4" ></video>

<!-- Etiqueta con imagen fija más dos formatos de video -->
<video poster="brocha.jpg" width="480px" height="360px">
	<source src="PinturaSecandose.mp4" type="video/mp4">
	<source src="PinturaSecandose.webm" type="video/webm">
</video>

Muy versátil, ¿no? Ahora todos tus amigos podrán ver el video de 4h de la pintura de tu cocina secándose, mientras tu grabas otro emocionante video de tu gato durmiendo. Pero, ¿que tiene que ver esto con la cámara web? La etiqueta video requiere un archivo de video ya grabado ¿o no?… pues no, no tiene porque ser un video pregrabado.

Conectando tu webcam a la etiqueta Video

Bueno, vamos a hacer esto rápido. Antes que nada te explico que el acceso a la cámara está, por ahora, limitado a unos pocos navegadores: Opera (desktop y móvil) desde la versión 12, Chrome desde la versión 21, Firefox desde la versión 18 (disponible desde finales de octubre/2012), y leí por ahí que posiblemente IE lo soporte desde la versión 11; con esto en poco tiempo tendremos soporte en los principales navegadores. Un detalle más: la página debes abrirla desde un servidor web para poder acceder a la cámara de tu equipo. Puedes instalar Apache u otro servidor para hacer pruebas localmente (mira en mi post anterior sobre como instalarlo en ubuntu), o abre el ejemplo en jsFiddle con el link que está al final del post.

Comencemos con un poco de HTML y CSS para preparar nuestra página web:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Prueba de cámara Web</title>
	<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
	<style type="text/css">
		.contenedor{ width: 350px; float: left;}
		.titulo{ font-size: 12pt; font-weight: bold;}
		#camara, #foto{
			width: 320px;
			min-height: 240px;
			border: 1px solid #008000;
		}
	</style>
	<script type="text/javascript">
		//El código Javascript está en la siguiente sección del post
	</script>
</head>
<body>
	<div id='botonera'>
		<input id='botonIniciar' type='button' value = 'Iniciar'></input>
		<input id='botonDetener' type='button' value = 'Detener'></input>
		<input id='botonFoto' type='button' value = 'Foto'></input>
	</div>
	<div class="contenedor">
		<div class="titulo">Cámara</div>
		<video id="camara" autoplay controls></video>
	</div>
	<div class="contenedor">
		<div class="titulo">Foto</div>
		<canvas id="foto" ></canvas>
	</div>	
</body>
</html>

Básicamente tenemos tres bloques en el cuerpo del HTML: vemos un div con 3 botones para iniciar el video, para detenerlo, y para tomar una foto (lo de la foto va para después), más abajo tenemos un segundo div que contiene una etiqueta video y un tercer div que contiene una etiqueta canvas.

En encabezado tenemos una referencia a jQuery, que va en la versión 1.8.2 al momento de publicar el post; este lo usaremos como herramienta para acceder al DOM (estructura del html) por javascript. Personalmente creo que hay que aprender Javascript antes de aprender a usar algún framework o librería (como jQuery, DOJO, Prototype, YUI…), porque un framework/librería solo va a ayudarte a hacer más fácilmente lo que igual podrías hacer «a mano».

En el encabezado también tenemos algunos estilos definidos para mostrar el layout en pantalla. En este punto debes tener algo como esto:

Layout de la página de prueba de video HTML5

Ahora el código javascript. Este, debes colocarlo en el encabezado, después de la definición de los estilos puedes ver el espacio donde va situado (o si prefieres puedes colocarlo en un archivo externo):

//Nos aseguramos que estén definidas
//algunas funciones básicas
window.URL = window.URL || window.webkitURL;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || function(){alert('Su navegador no soporta navigator.getUserMedia().');};

jQuery(document).ready(function(){
	//Este objeto guardará algunos datos sobre la cámara
	window.datosVideo = {
		'StreamVideo': null,
		'url' : null 
	};
	
	jQuery('#botonIniciar').on('click', function(e){
		//Pedimos al navegador que nos de acceso a 
		//algún dispositivo de video (la webcam)
		navigator.getUserMedia({'audio':false, 'video':true}, function(streamVideo){
			datosVideo.StreamVideo = streamVideo;
			datosVideo.url = window.URL.createObjectURL(streamVideo);
			jQuery('#camara').attr('src', datosVideo.url);
		}, function(){
			alert('No fue posible obtener acceso a la cámara.');
		});

	});

	jQuery('#botonDetener').on('click', function(e){
		if(datosVideo.StreamVideo){
			datosVideo.StreamVideo.stop();
			window.URL.revokeObjectURL(datosVideo.url);
		};
	});
});

Al hacer clic en el botón botonIniciar se ejecuta la función navigator.getUserMedia del navegador. Esta recibe tres parámetros: el primero con la configuración (pediremos video, sin audio), el segundo es una función que se ejecutará cuando obtengamos acceso a la cámara, y el tercero es una función que se ejecutará si no se puede obtener acceso a la cámara.

Si logramos obtener una fuente de video, generamos un url de «dispositivo de video» que podemos usar como origen para nuestra etiqueta video (como dije antes, no tiene que ser un video pregrabado). Este url, junto con el flujo de video lo almacenamos en el objeto que definimos al principio para poder detener el video con el segundo botón. Si tienes una cámara web conectada a tu equipo puedes probar este código y tendrás acceso a tu cámara.

Una aclaratoria sobre «obtener acceso a un dispositivo de video»: al ejecutar la función navigator.getUserMedia le estamos pidiendo al navegador que nos provea acceso a «algún» dispositivo de audio y/o video (según el primer parámetro), pero por supuesto no vamos a acceder a la cámara y grabar a los usuarios sin pedir permiso, por esa razón el navegador probablemente muestre un mensaje al usuario indicándole que la página quiere tener acceso a la cámara web. El usuario puede aceptar o rechazar la petición, e incluso puede indicarle cuál «dispositivo» usar. Esto es útil si, por ejemplo, estás abriendo esta página desde tu móvil o tablet y este cuenta con dos cámaras (frontal y trasera).

Captura de foto desde la cámara

Ya tenemos video! ahora hagamos algo interesante con él. Debajo del botón botonDetener colocamos el código para manejar el clic del botón botonFoto:

jQuery('#botonFoto').on('click', function(e){
	var oCamara, 
		oFoto,
		oContexto,
		w, h;
		
	oCamara = jQuery('#camara');
	oFoto = jQuery('#foto');
	w = oCamara.width();
	h = oCamara.height();
	oFoto.attr({'width': w, 'height': h});
	oContexto = oFoto[0].getContext('2d');
	oContexto.drawImage(oCamara[0], 0, 0, w, h);

});

El código es corto y simple: primero obtenemos una referencia a la etiqueta video (llamada camara) y otra a la etiqueta canvas (llamada foto), redimensionamos el canvas para que coincida con el tamaño del video. Luego pedimos al canvas un contexto de dibujo; este es el que realiza las operaciones de dibujado sobre el canvas. Usaremos el método drawImage del contexto para dibujar sobre el canvas la imagen actual del video (el fotograma que esté mostrando al momento de hacer clic en botonFoto).

A la función drawImage le pasamos como parámetros: el objeto que representa a la etiqueta video (escribimos oCamara[0] para pasarle el elemento del DOM, no el objeto/arreglo de jQuery), y otros cuatro parámetros que representan la posición dentro del canvas donde se comenzará a dibujar (coordenadas x y y del canvas) y el tamaño que tendrá la imagen dibujada (podríamos escalar la imagen cambiando estos valores).

Si tienes una cámara web instalada ya puedes probar el código y tomar una foto desde tu página web.

Etiquetas Video y Canvas trabajando juntas para tomar una foto

También puedes ver un ejemplo funcionando en jsFiddle. ¿Primera vez en jsFiddle? solo abre el link y presiona el botón run que está arriba a la izquierda, puedes modificar el código y presionar run de nuevo para hacer pruebas, pero no presiones update para no llenar la base de datos de jsFiddle con «pruebas» 🙂 .

Una recomendación: debes leer un poco más acerca de los atributos width y height de las etiquetas canvas y video (ojo: no son los mismos atributos css width y height, que podrían tener diferente valor), para que tengas una idea clara de como afectan la calidad y resolución de la imagen tomada. En este ejemplo, le dí a ambas etiquetas un ancho fijo de 320px, y una altura variable (de al menos 240px), de manera que se mantenga el aspecto (ratio aspect) del video y de la foto, y que la foto tenga al menos la misma calidad que provee la cámara. Más abajo te dejo el vínculo de las definiciones de estas etiquetas en la página de la W3C.

Claro que, teniendo la foto en pantalla probablemente quieras hacer algo más con ella, por ejemplo agregarle un marco o aplicar un filtro (como los de instagram); para esto puedes usar el objeto Context del canvas (el que usamos hace poco). Si deseas guardar la imagen en el servidor puedes hacerlo con AJAX (jQuery te facilitará mucho el trabajo) y algo de código en PHP, JSP o APS, incluso puedes determinar las medidas y tamaño de la imagen antes de enviarla.

En el próximo post veremos como HTML5 nos permite obtener una vista previa de una imagen seleccionada por el usuario antes de enviarla al servidor, y veremos como determinar las medidas (en pixels) y el tamaño (en bytes) de la imagen.

Referencias

  • Excelente fuente de información sobre HTML5 (y video): HTML5ROCKS
  • Definición de la etiqueta video (material técnico de la W3C)
  • Definición de la etiqueta canvas (material técnico de la W3C)
  • Explicación sobre captura y flujos de medios (material técnico de la W3C)
  • Formatos de video soportados por varios browsers

Cita del día

A painter paints his pictures on canvas. But musicians paint their pictures on silence. We provide the music, and you provide the silence.
Leopold Stokowski

, ,

116 respuestas a “Acceso a la cámara con HTML5”

  1. JUSTO ESTABA BUSCANDO ESTO PARA IMPLEMENTARLO EN SISTEMITA DE FIN DE CICLO EL PROBLEMA ES QUE NO ME GENERA LA FOTO LO DE LA CAMARA EL PLAY Y STOP TODO CORRECTO PERO LO DE LA FOTO NO ME SALE PERO TAMPOCO ME GENERA NINGUN ERROR.

    CUAL CREES Q SEA EL PROBLEMA??

    GRACIAS DE ANTEMANO SALUDOS DESDE PERU

  2. Tendría que ver tu código, pero puedes intentar esto: agrega un console.log() (o un alert()) en el clic del botón para estar seguros de que está tomando la foto. Agrega una etiqueta img al html, y después de
    oContexto.drawImage(oCamara[0], 0, 0, w, h);
    copia la imagen del canvas con
    jQuery('img').attr('src', oContexto.toDataURL(“image/png”));
    Así sabrás si el problema es solo de visualización (si puedes ver la imagen en el img) o si ni siquiera está copiando algo al canvas (si la imagen tiene el tamaño del canvas pero sale en blanco). Por cierto, estás trabajando en un servidor, no? aunque sea un servidor local (Apache en tu equipo): En Google Chrome por ejemplo no puedes «tocar» urls que comiencen por «file://», incluso si están en el mismo directorio que tu html.

  3. he copiado tu codigo pero en el pc si funciona la activacion de la camara y puedo ver video mas tomar la foto no puedo. en dispositivo movil no puedo acceder ni al video ni la foto me puedes ayudar

  4. Hola Roimer, me podrias ayudar, como puedo hacer para guardar la foto tomada en un directorio, de antemano gracias

    • Saludos David! bueno, lo primero es que la imagen está en el navegador dibujada en un canvas, así que debes leer los bytes de la imagen (con Javascript) y convertirlo en un formato que puedas enviar al servidor. Algo así (Ojo: el código está incompleto :P):


      //Obtienes el contexto del canvas, y lees la imagen codificada en Base64:
      var oContexto = document.getElementById("foto").getContext("2d");
      var oData = {
      cMiFoto: oContexto.toDataURL(“image/png”),
      cUnParametro: "algun valor",
      nOtroParametro: 3.1415
      };
      //Envías la imagen como un post normal a una página ASP, PHP, servicio web, etc.
      jQuery.ajax({
      url: "PaginaQueRecibeYGuardaFoto.php",
      type: "post",
      data: oData
      });

      Del lado del servidor programas el código que recibe los parámetros. El parámetro cMiFoto es una cadena que debes convertir desde Base64 a un array de bytes, pero la forma de hacerlo depende de con qué estés programando: en ASP .Net yo usaría convert.FromBase64() para la conversión, y un FileStream para guardarla en disco.

      Aquí tienes un ejemplo de como convertir de Base64 a imagen (en C++, creo): http://www.dailycoding.com/Posts/convert_image_to_base64_string_and_base64_string_to_image.aspx ; en el ejemplo del link generan un objeto Image, pero en lugar de eso debes usar el método save para guardarlo en una carpeta en disco. NOTA: la cadena que te genera el canvas comenzará por algo como «data:image/png;base64,», debes quitar ese encabezado antes de tratar de convertir en imagen, la verdadera imagen comienza después de la coma.

      • Saludos Roimer, muchas gracias por tu ayuda, estoy trabajando con php, y creo que lo que tengo que hacer desde el lado del servidor es lo siguiente:
        $imagen = $_POST[‘data’];
        //luego codificarla a base64
        $imagenB64 = base64_encode($imagen);
        y esta $imagenB64 hasta aqui creo que la puedo guardar asi como esta en un campo de la bdd para luego decodificarla y mostrarla donde la necesito.
        Porque para guardar a un directorio se me carga una imagen vacia lo que hago es lo siguiente:

        $destino=»directorio/».$imagenB64;
        $fp=fopen($destino,»w»);
        fputs($fp,fread(fopen($destino,»r»),filesize($destino)));
        fclose($fp);
        corrigeme por favor que es lo que estoy haciendo mal o que me recomiendas que puedo hacer, y nuevamente gracias por tu ayuda.

  5. No sé programar en PHP, pero creo que vi tres problemas. Primero, en mi ejemplo estoy enviando al servidor tres variables (están dentro del objeto data, pero son tres), de ellas la que debes leer es cMiFoto (pero si fue que le cambiaste el nombre olvida este punto 🙂 ).

    Lo segundo es que la imagen que estás recibiendo ya está en base 64 (es una cadena de caracteres) y la puedes guardar tal y como está en base de datos (claro, si tu intensión es guardarla en base de datos).

    Lo tercero es si quieres guardarla en disco:
    * La imagen (desde ajax o desde base de datos) está en Base64, así que debes decodificarla primero:
    $imagenBytes = base64_decode($imagenB64);
    * Creas un objeto resource (la variable $imagenR) a partir de la imagen y lo guardas con la función imagepng:
    $destino = "directorio/miArchivoGuardado.png"
    $imagenR = imagecreatefromstring($imagenBytes)
    imagepng($imagenR, $destino)

    * Por cierto, en tu código tenias un lío con el path de la imagen 🙂

    Te advierto de nuevo que no sé mucho de PHP, jeje, esto lo saqué de aquí http://lv.php.net/imagecreatefromstring y aquí http://www.php.net/manual/es/function.imagepng.php .

    NOTA: Recuerda que debes quitar el «data:image/png;base64,» que está al principio de la imagen que recibiste en PHP (o quítaselo por Javascript antes de enviarlo).

    • Saludos Roimer, nuevamente muchas gracias por tu ayuda voy a probar lo que tu me indicas a ver como va con esto, pero por lo pronto ya guardo la imagen codificada en la base y la muestro en donde la necesito, esta todo chevere gracias y felicitaciones por tu blog.

      • Hola david cornejo, soy nueva en esto… pero lo estoy estudiando y estoy muy interesada en practicar… no se tal vez e puedas explicar mas acerca de como pasar el canvas a formato de imagen y guardarlo automáticamente cuando tome la foto desde la cámara web…. muchas gracias

        • Claro Leidy K. con gusto lo primero es indicarte que trabajo con php, y para guardar la imagen en el disco hago lo siguiente: primero al momento de tomar la foto al nombre de la imagen le asigno en un input tipo hidden (fotoTom), luego de eso obtengo la imagen de la siguiente manera:

          $fotoTom = $_POST[‘fotoTom’];//obtengo el nombre de la imagen del input hidden
          if($fotoTom!=»){//veo si al momento de guardar el registro en la pantalla que tomo la foto se haya tomado la foto
          $image = explode(‘base64,’,$fotoTom);//separar el nombre original de la imagen sin base64 del nombre de la imagen
          $fotoTom = $cedula.’.jpg’;//asigno el nuevo nombre de la imagen
          $handle = opendir($dir);//abro el directorio donde voy a guardar la imagen
          file_put_contents(‘/directorio_donde_va_la_imagen/’.$fotoTom,base64_decode($image[1]));//y por ultimo guardo la imagen en el servidor
          }

          Claro todo esto previo las indicaciones que se indican anteriormente.
          Espero haberte podido ayudar

      • Buena tarde David, espero estes bien….. ahora que la camara toma la foto, la guarda automáticamente….. quiero compartirla en facebook….. y mira estoy utilizando este codigo… pero quiero que quede como una imagen normal en facebook en las fotos del que la comparta…….
        mira, tal vez me puedas colaborar que me hace falta o que le puedo cambiar?

        Te lo agradeceria mucho….

  6. Roimer tu código si es soportado por tablets y dispositivos android y funciono muy bien, creo que me ganaron la pregunta de como guardarla en el servidor gracias.

  7. Ahora el detalle es que la imagen la tengo en png extraido del canvas con este codigo
    btnPhoto.addEventListener(«click», function() {
    context.drawImage(video, 0, 0, 320, 240);

    window.open(canvas.toDataURL(«image/png»));

    });
    lo que hago es mandar esa imagen png a otra ventana, estoy buscando como guardarla en una carpeta del servidor, mi pc la tengo habilitada como tal.

  8. Saludos Marcos, Si vas a guardarla en el servidor entonces puedes seguir los pasos que describo en el otro comentario más arriba (mi comentario del 20 de mayo): la idea básicamente es mandar al servidor el string que te devuelve la función canvas.toDataURL() mediante un POST, y del lado del servidor (con PHP, ASP, JSP, lo que tengas disponible) lees el string y lo conviertes en una imagen que puedas guardar.

    Si estás trabajando con PHP entonces mi comentario del 21 de mayo tiene el código «central» que se encarga del proceso. Cualquier duda comenta a ver si te puedo ayudar 🙂

  9. Buenas noches amigo. me parece excelente tú explicación. Quiero hacerte algunas preguntas: ¿Utilizando esta herramienta podré identificar rostros? ¿Exisitrá la forma de hacer un login de usuarios para acceder a un módulo en específico? Gracias de antemano.

    • Hola Ramón. Respecto a la primera pregunta: definitivamente si. Una vez que tienes la foto del usuario la envías al servidor y desde allí aplicas algún algoritmo de reconocimiento de imágenes (o mejor: usa una librería) para determinar qué tanto se parece este rostro al «guardado» en base de datos. Nunca lo he hecho, pero procedimiento sería algo como esto: Al registrar al usuario le pides tomarse una foto con buena iluminación y fondo claro, tu introduces esa foto a la base de datos (o la guardas en disco con un ID) tal vez tengas que «procesarla» primero (depende de la librería que uses), y al loguearse el usuario usas una librería de reconocimiento facial para comparar la nueva foto con la vieja (si el usuario ingresa el nombre/ID y vas a usar la foto como password) o con todas las registradas (si planeas usar solamente la foto, sin Nombre/ID), y ella te dirá con cierto grado de probabilidad si ambos rostros son de la misma persona. Búscate un teléfono con Android 4.0 para que lo veas funcionando, entre las opciones de bloqueo hay una para desbloquear por reconocimiento facial.
      Respecto a la segunda pregunta, es fácil una vez que sepas quien es el usuario (independientemente del método de autenticación): algún usuario administrador (o tu sistema, según tipo de usuario) define a qué módulos se le permite ingresar a cada usuario o tipo de usuario.

  10. Muchas gracias por tu pronta respuesta. Aplicaré tus conocimientos y posteare mediante este medio la información para que a todos les sirva. Saludos desde Maracaibo, Venezuela. Es bueno conocer amigos.

  11. copie el codigo en un HTML, y funciona muy bien los botones de Iniciar, Detener, Foto, todo esta muy bien solo que la imagen quiero grabarla en un directorio y ponerle un nombre yo Ejempli: daniel.jpg, el nombre que este como campo para escribir el nombre… gracias roimer garica ….

  12. Saludos Daniel, te refieres a enviar y guardar la imagen en el servidor, ¿no?
    Sería así: después de tomar la foto (mismo botón u otro) debes obtener la imagen del canvas (codificada como base64) y enviarla al servidor. Este es el ejemplo usando AJAX:

    //Obtienes el canvas, y lees la imagen codificada en Base64:
    var oCanvas = document.getElementById("foto");
    var oData = {
      cMiFoto: oCanvas.toDataURL(“image/png”),
      cNombreArchivo: "daniel.png" //el nombre lo leerías de un input
    };
    //Envías la imagen como un post normal a una página ASP, PHP, servicio web, etc.
    jQuery.ajax({
      url: "PaginaQueRecibeYGuardaFoto.php",
      type: "post",
      data: oData
    });
    

    Ahora, del lado del servidor tendrías un servicio/página que reciba la imagen. Este ejemplo está en PHP (dependerá de qué lenguaje uses en servidor)…. ojo, que casi no sé PHP, lo pongo porque es lo que usa todo el mundo, jeje:

    $imagenB64 = $_POST[‘cMiFoto’];
    $nombreArchivo = $_POST[‘cNombreArchivo’];
    $imagenBytes = base64_decode($imagenB64);
    $destino = "directorio/".$nombreArchivo
    $imagenR = imagecreatefromstring($imagenBytes)
    imagepng($imagenR, $destino)

    NOTA: la cadena enviada en _cMiFoto_ comienza por “data:image/png;base64,” (o “data:image/jpg;base64,”), esto *creo* debes quitárselo antes de usar la función _base64_decode_; en ASP.Net es necesario eliminarlo antes de la conversión, pero en PHP no estoy seguro. Aquí hay más información de como hacerlo el guardado en PHP: http://lv.php.net/imagecreatefromstring y http://www.php.net/manual/es/function.imagepng.php .

    Saludos, y comenta si lo lograste o si tienes problemas 🙂

  13. hola que tal al usar tu codigo todo funciona perfectamente. solo que si se mueve mucho la imagen el video se queda trabado.¿Sabes que podria ser?

    • Saludos Jorge, te refieres a que si te mueves mucho frente a la cámara el video se ve como «cortado» (en lugar de movimiento fluido) ¿no?: Si es así solo se me ocurren dos razones:
      1) La cámara trabaja a pocos FPS (no me refiero al video generado, sino a la capacidad de la cámara para grabar). Esto me pasaba con mi cámara anterior, ahora uso una Genius y «casi» no pasa.
      2) Tu navegador o tu equipo (PC/móvil/tableta…) no es lo suficientemente rápido para renderizar el video en pantalla.
      Puedes verificar si es el primer caso usando cualquier otro software que te permita ver la cámara (como Skype, o algún otro software que no sea web).
      Si no, el segundo punto lo puedes probar primero en otro navegador y luego en otro equipo (preferiblemente un PC «rápido»). También puedes probar en tu mismo equipo con algún chat web (). Con esto estarás seguro de si tu problema es de código o de hardware.
      Otra cosa que podrías intentar es reducir el tamaño del canvas: eso podría hacer más rápido el renderizado, pero solo si es el segundo caso.

      • Muchas gracias ya probe con otro equipo (una laptop con su webcam integrada) y funciona de muy bien gracias.

        quise implementar el la funcion para guardarlo pero me marca error de sintaxis en esta linea.

        var oData = {
        cMiFoto: oContexto.toDataURL(“image/png”),
        cNombreArchivo: «daniel.png» //el nombre lo leerías de un input
        };

        podrias ayudarme?

    • Jorge: ya vi el problema, fue mi error en el comentario del 16 de agosto 😛 donde dice ** cMiFoto: oContexto.toDataURL(“image/png”), ** fíjate que las comillas dobles son “comillas tipográficas”. Supongo que copiaste directamente y te las llevaste 🙂 solo elimina las comillas de esa línea y la siguiente y escríbelas de nuevo.

  14. excelente ahora marca este error

    Uncaught TypeError: Object # has no method ‘toDataURL’

    sera por que estoy usando este jquery?

    saludos y gracias por tu ayuda.

    • Disculpa, pero tu comentario había caído en Spam, lo acabo de leer. Fue un despiste mio: la función toDataURL viene del canvas, no del contexto del canvas:

      var oCanvas = document.getElementById("foto");
      var oData = {
        cMiFoto: oCanvas.toDataURL(“image/png”),
        cNombreArchivo: "daniel.png" //el nombre lo leerías de un input
      };
      
    • Hola Leidi, acabo de probar tu código: veo que la cámara (el elemento video) tiene width: 100%; y está dentro de un div con width: 50%;. En mi monitor (1920×1080) la imagen ocupa media pantalla aunque la resolución de mi cámara es pequeña (la imagen tiene un área unas 5 veces mayor). Si dejas el ancho de la cámara en width: auto; tanto el video como la foto final tendrán exactamente la resolución que tenga la cámara del usuario. NOTA: de todas formas asignale un max-width al video (¡en pixeles, no porcentaje!), así, si el usuario tiene una cámara de mucha resolución la imagen no va a pasar de cierto tamaño.

      La otra opción es que definas un ancho fijo (no porcentaje) para el video, y deja la altura en automático para que no quede distorsionada. Para cualquiera de las dos opciones toma en cuenta que el tamaño final de la imagen, en pixeles, va a incidir directamente en la velocidad de envío (si la vas a enviar al servidor), así que debes probar hasta estar segura que la velocidad es aceptable.

      Prueba a ver y cualquier cosa comenta por aquí de nuevo 🙂

  15. Hola, Se puede añadir una imagen a la vista de la camara, tipo mascara, marca de agua o mosca(algo parecido a los logos de las TV).

    Gracias buen trabajo

    • Hola Carlos, serían dos pasos:
      * Para el video: Método 1: puedes colocar un segundo canvas sobre el primero, con background-color: transparent y position:absolute. El 2º canvas sería del tamaño de la imagen que quieras. al momento de activar la cámara (o apenas se cargue la página) pintas en ese canvas el logo, usando la función drawImage(). Para que quede semitransparente, antes de usar drawImage() debes establecer la propiedad globalAlpha del contexto a 0.5. Método 2: Si tienes prisa olvida el canvas y coloca un div con la imagen de fondo y controlas la opacidad con css.

      * Para la foto: justo después de tomar la captura del video en el 1º canvas debes establecer la propiedad globalAlpha del contexto a algún valor entre 0 y 1 (prueba con 0.5) y luego pintar tu imagen sobre el canvas usando drawImage(). IMPORTANTE: después de pintar la marca de agua recuerda establecer el globalAlpha a 0, en caso de que debas tomar una segunda foto.

      En el artículo usé drawImage() para pintar del video al canvas: el primer parámetro de la función puede ser un objeto video, image, o canvas. La documentación de esta función la tienes aquí (en inglés): http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/#dom-context-2d-drawimage

  16. Hola, muy bueno el tuto. Lo que sí, no anda para utilizar la camara trasera, solo toma la camara frontal y de ninguna manera puedo seleccionar la trasera, se te ocurre como puedo lograr esto? Gracias!

    • Saludos Manuel, Me extrañó un poco tu pregunta porque cuando publiqué el artículo probé el código con dos cámaras con Google Chrome desktop y unos meses después con Google Chrome for Android y en ambos al salir la barra para permitir/bloquear la cámara había un botón a la derecha para seleccionar el dispositivo de video; en mi PC incluso salia la capturadora de TV.
      Bueno, me puse a investigar y encontré este hilo { https://code.google.com/p/chromium/issues/detail?id=167264 } allí explican que Chrome dejó de mostrar la opción en pantalla desde Diciembre de 2012! ahora la cámara por defecto hay que especificarla desde la configuración pero solo está disponible en la PC, lo que veo está muy mal hecho. En fin: aparentemente quitaron la opción en Chrome, y el navegador por defecto de Android ni siquiera soporta la cámara. Voy a probar en Firefox for Android (no tengo iOS para probar), pero no creo que se pueda tampoco 🙁

  17. Hola, hay manera de guardar el dibujo canvas en mi base de datos
    enviándolo desde un formulario ?

    • Hola Andrés, si se puede, chequea los comentarios anteriores: en mi comentario del 16/ago/2013 hay un ejemplo para enviar la imagen al servidor (en BASE64) usando javascript, y cómo convertirla de nuevo en un archivo de imagen con PHP para guardarlo en disco. Si lo que quieres es guardar en base de datos entonces desde PHP podrías tomas el BASE64 que enviaste y guardarlo directamente en un campo de texto (BASE64 es un string) y cuando necesites mostrar la imagen conviertes ese texto de vuelta en una imagen (o también: puedes inyectar el string directamente en el src de un elemento img).
      Otra posibilidad: en lugar de guardar la imagen como BASE64 podrías convertirla en imagen al momento de subirla y la guardas en un campo blob de la base de datos; de todas formas te recomiendo decidir si te conviene más guardar las imágenes en disco (si se usarán muy seguido o son grandes) o en base de datos (si casi no se usarán). Y si lo haces en base de datos: decidir si las guardas en BASE64 (se insertan directamente en los src de las etiquetas img) o como arreglos de bytes en campos tipo blob/bytearray (que podría ser más cómodo si vas a manipular las imágenes o «servirlas» por medio de un controlador).

  18. Excelente, me gusto.
    solo no logro activar la camara con ANDROID dice que el navegador no soporta.
    Seguire buscando la opcion…

    Muy agradecido con tu post.

    • Saludos Juan!
      ¿Te sale el mensaje «Su navegador no soporta navigator.getUserMedia().», no? lo que ocurre es que el navegador Android aun no tiene soporte para getUserMedia, por ahora puedes probarlo desde android con Chrome, Firefox, Opera Mobile y Blackberry Browser (OK, este último no, amenos que RIM saque también una versión para Android 😛 ).
      Puedes verificar el soporte de los navegadores de escritorio o móviles en caniuse.com (soporte de getUserMedia y stream: http://caniuse.com/stream ), es mi herramienta preferida para verificar el soporte de CSS y HTML5.

  19. Hola Romier, estoy probando tu codigo todo bien, solo no me toma la foto, es decir no aparace en el canvas. Estoy con firefox

    • Disculpa Roimer, pero no me sale ningun error, solo no toma la foto, visite tu sitio y veo que funciona, que puede ser???

      • Saludos Luis, tardé bastante en responder y supongo que ya resolviste, de todas formas así es como pruebo (con firebug o la consola de chrome) cuando no me funciona al código: primero que nada, como mi código (el jsfiddle) te funcionó podemos descartar que sea un problema de soporte; ¿el video si se muestra? si es así entonces verifica con firebug que el canvas de la foto tiene ancho y alto (no me refiero a las propiedades o el css: verifica el tamaño «real» que le da el navegador), luego coloca un console.log('click OK') en el manejador del clic de botonFoto para verificar que realmente se esté ejecutando; luego, justo antes del drawImage otro console.log({w:w, h:h}) para verificar que ambas medidas son mayores a cero.
        Otra posibilidad (aunque esto si debería mostrar un error en la consola): es posible que no te funcione la cámara o la foto si estás probando desde un archivo «local», en chrome por ejemplo el año pasado estaba haciendo pruebas locales con la cámara y no funcionaba porque estaba abriendo una página html de forma «local», cuando la abrí en el mismo equipo usando apache me funcionó perfecto. Otra cosa es que drawImage aplica la política del «mismo origen»: si el origen desde el cual vas a copiar la imagen está en otro dominio (un video de youtube, una imagen de flickr…) entonces drawImage no lo va a copiar en tu canvas (o si lo copia, luego no te permitirá leer el canvas para guardar la imagen).

  20. Buenas Tardes Roimer! Cordial saludo. Soy Ingeniero de Sistemas de Medellín-Colombia, Actualmente acabo de implementar esta nueva maravilla de HTML5 pero me ha surgido un inconveniente de procedimiento… la pregunta es: ¿Es posible permitir que mi camara web se active automáticamente sin tener que preguntar si deseo permitir usar mi cámara cada que entro a una pagina?

  21. Buenas tardes Cristian! me temo que la respuesta corta es no 🙁
    La confirmación es parte de la seguridad del navegador para impedir que un sitio web «malintencionado» grabe al usuario sin su permiso. Personalmente creo que el navegador debería incluir un checkbox en la barra que diga «permitir siempre acceso a la cámara desde este sitio», así como cuando usas la cámara desde algún chat hecho en flash.
    Lo mejor que se puede hacer es mantener el video «activo» (me refiero al objeto streamVideo) para que el usuario solo tenga que dar permiso una vez durante la sesión actual; similar a la forma en que https://soundcloud.com te deja navegar sin detener la música que estés escuchando (la navegación se hace con ajax, e.g. jQueryMobile)

  22. CRISTIAN MEJÍA SUÁREZ, si se puede, claro que tendrías que permitir el acceso a la cámara al menos la primera vez, la solución es que debes manejar certificados de seguridad ( SLL ) en tu hosting ( https ), si tu hosting tiene certificados de seguridad cuando un usuario acceda a tu pagina con el aplicativo de la cámara, solo le preguntara la primera vez, las siguientes recordara las preferencias. Eso es lo máximo que se puede hacer por seguridad.

  23. Gracias por el artículo… por si alguno se anda rompiendo la cabeza al momento de guardar la foto en Php (como fue mi caso XD)… solo quiten los espacios que trae el post ajax
    $imagenB64 = $_POST[‘cMiFoto’];
    $img = substr(($imagenB64),strpos(($imagenB64),’,’)+1); //Separamos el contenido de la imagen
    $encodedData = str_replace(‘ ‘,’+’,$img); //reemplazamos los espacios en blanco para que la imagen no se guarde corruptamente
    $imagenBytes = base64_decode($encodedData); //descodificamos
    file_put_contents((‘foto.png’), $imagenBytes); //guardamos en algun directorio

    Saludos…

    • Y gracias a ti Raul por el comentario 🙂
      Para los curiosos: lo que ocurre es que la función $_POST() asume (como es debido) que los parámetros son enviados codificados así que los «decodifica» al leerlos. Por eso, los «+» que forman parte de la codificación BASE64 de la imagen son cambiados por espacios, y es necesario cambiarlos de nuevo desde PHP.

  24. Hola, primero que nada deseo felicitarte por tu blog es muy bueno, segundo, tengo una duda, ya que el código si funciona en la tablet pero tiene 2 cámaras, en vez de usar la cámara trasera, usa La cámara frontal, hay alguma manera de configurar esto u obligarle a que Tome la trasera? De antemano gracias por la atención. Y espero Con ansias pronta respuesta

    • Saludos POULETTE López, disculpa la respuesta tan tarde y de paso a medias (he tenido mucho trabajo esta semana :p… aunque eso es bueno 🙂

      Puedes usar la función MediaStreamTrack.getSources para obtener la lista de «Origenes» disponibles en el dispositivo. Recorres esa lista y busca los de tipo «video», y entre estos toma el primero que tenga la propiedad facing=»user». Este es un mini ejemplo:

      MediaStreamTrack.getSources(function(sourceInfos) {
          var origenVideo = null;
          for(var i = 0; i<sourceInfos.length; i++){
              var origen = sourceInfos[i];
              if(origen.kind==='video' && origen.facing = 'user'){
                  var camaraFrontal = origen.id;
              };
          };
      });
      

      Luego, puedes usar pasarle ese ID en el primer parámetro de getUserMedia para indicar que ésa es la cámara que quieres. Claro, igualmente el navegador pedirá permiso al usuario para usar la cámara, pero por defecto tomará la cámara que tu le sugieras.

      Aquí tienes un jsFiddle con un ejemplo más completo y funcionando http://jsfiddle.net/roimergarcia/kBpGz/embedded/result/, lo probé en mi teléfono y me permite seleccionar cualquiera de las dos cámaras (claro: el ejemplo es para que el usuario seleccione la cámara, pero es fácil modificarlo para que sea tu código el que lo indique); está a pantalla completa, perfecto para que lo pruebes directamente en tu teléfono o tableta, en este otro link está el código completo: http://jsfiddle.net/roimergarcia/kBpGz/embedded/result/
      NOTA: en mi laptop solo tengo una cámara, y la propiedad facing de la misma aparece como una cadena vacía! así que pendiente si tu web también se verá en un equipo con una sola cámara.
      Espero que te sirva, por favor pruebalo y comenta de nuevo a ver si me animo de escribir un artículo actualizado sobre el tema 🙂

  25. Hola que tal muy buen aporte, felicidades
    solo que tengo un problema para guardar la imagen en una carpeta, te dejo mi codigo , no ejecuta el boton guardar..
    gracias…

    Prueba de cámara Web

    .contenedor{ width: 350px; float: left;}
    .titulo{ font-size: 12pt; font-weight: bold;}
    #camara, #foto{
    width: 320px;
    min-height: 240px;
    border: 1px solid #008000;
    }

    //Nos aseguramos que estén definidas
    //algunas funciones básicas
    window.URL = window.URL || window.webkitURL;
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || function(){alert(‘Su navegador no soporta navigator.getUserMedia().’);};

    jQuery(document).ready(function(){
    //Este objeto guardará algunos datos sobre la cámara
    window.datosVideo = {
    ‘StreamVideo’: null,
    ‘url’ : null
    };

    jQuery(‘#botonIniciar’).on(‘click’, function(e){
    //Pedimos al navegador que nos de acceso a
    //algún dispositivo de video (la webcam)
    navigator.getUserMedia({‘audio’:false, ‘video’:true}, function(streamVideo){
    datosVideo.StreamVideo = streamVideo;
    datosVideo.url = window.URL.createObjectURL(streamVideo);
    jQuery(‘#camara’).attr(‘src’, datosVideo.url);
    }, function(){
    alert(‘No fue posible obtener acceso a la cámara.’);
    });

    });

    jQuery(‘#botonDetener’).on(‘click’, function(e){
    if(datosVideo.StreamVideo){
    datosVideo.StreamVideo.stop();
    window.URL.revokeObjectURL(datosVideo.url);
    };
    });
    });

    //El código Javascript está en la siguiente sección del post

    jQuery(‘#botonG’).on(‘click’, function(e){
    //Obtienes el canvas, y lees la imagen codificada en Base64:

    var oCanvas = document.getElementById(«foto»);
    alert(oCanvas);
    var oData = {
    cMiFoto: oCanvas.toDataURL(«image/png»),
    cNombreArchivo: «foto.png» //el nombre lo leerías de un input

    };
    alert(oData);
    //Envías la imagen como un post normal a una página ASP, PHP, servicio web, etc.
    jQuery.ajax({
    url: «guardar.php»,
    type: «post»,
    data: oData

    });
    });

    jQuery(‘#botonFoto’).on(‘click’, function(e){
    var oCamara,
    oFoto,
    oContexto,
    w, h;
    oCamara = jQuery(‘#camara’);
    oFoto = jQuery(‘#foto’);

    w = oCamara.width();
    h = oCamara.height();
    oFoto.attr({‘width’: w, ‘height’: h});
    oContexto = oFoto[0].getContext(‘2d’);
    oContexto.drawImage(oCamara[0], 0, 0, w, h);
    jQuery(‘img’).attr(‘src’, oContexto.toDataURL(‘image/png’));

    });

    Cámara

    Foto

    • Buen día Jaquino!
      El código no pasó completo: en WordPress tienes que escapar el HTML en los comentarios. O mejor aun, prepara un jsfiddle como este: http://jsfiddle.net/roimergarcia/xxV2W/
      Ese link es un ejemplo completo funcionando (lo probé en Chrome y Firefox tanto en mi PC/Ubuntu como mi teléfono Android. Échale un ojo y cualquier coas vuelves a comentar por aquí 🙂

  26. Bueno, perdon por no darte credito, el codigo es tuyo yo lo estoy tratando de adaptar, gracias !!

  27. Muy bueno el ejemplo, pero tengo un inconveniente, al ejecutar la opción para Guardar sale el mensaje:

    TypeError: oContexto.toDataURL is not a function;

    En la línea
    jQuery(‘img’).attr(‘src’, oContexto.toDataURL(‘image/png’));

    Me podrían ayudar. Gracias.

    • Saludos Pablo,
      Antes de la línea que te da error coloca:
      console.log(oContexto)
      Y prueba con la consola del navegador abierta a ver que trae oContexto. Esa variable debería tener un contexto de un canvas, que obtienes mediante la función miCanvas.getContext(’2d’). ¿Qué navegador estás usando?

  28. excelente!!!! solo una cosa, como puedo transmitir el video y que al abrir otro explorador pueda ver la cámara solamente, esto es para transmitir en vivo

  29. Buen día amigo Roimer. He tomado tu idea y le he agrgado la funcionalidad de poder guardar la información de la imagen (foto capturada) del canvas en una imagen PNG con ayuda de AJAX (usando PHP como lenguaje del lado del servidor). Pueden ver el ejemplo aquí: http://kaarosu.com/demo/webKaam/ y si quieren ver los scripts, los pueden descargar desde aquí: http://www.kaarosu.com/tomar-foto-con-webcam-con-html5-y-guardar-su-imagen-via-ajax/

    Esta aplicación puede ser el inicio de grandes ideas, gracias por tu publicación. Saludos.

    • muchas gracias roimen y al codigo de kaarosu su ejemplo de guardarla en php lo necesitaba pero hay una forma donde solo active la camara y tome la foto sin necesidad de hacer el video y detenerlo

    • Hola kaarosu como estas? estuve viendo que resolviste como guardar la imagen en un servidor web. sera me puedes ayudar con ello? por fa. saludos Cordiales

  30. muchas gracias roimen y al codigo de kaarosu su ejemplo de guardarla en php lo necesitaba pero hay una forma donde solo active la camara y tome la foto sin necesidad de hacer el video y detenerlo

    • Hola Cristian, disculpa lo tarde de la respuesta, probablemente ya resolviste pero igual aquí va:
      1) Mantén en pantalla el canvas para que el usuario vea la foto, y el botón «tomar foto».
      2) Oculta el elemento Video y elimina los otros botones: el usuario solo tendrá que hacer clic en «Tomar Foto».
      3) El código que «inicia» la cámara (que inicia el video) lo colocas en el listener del clic del botón «Tomar Foto».
      4) El código que realmente toma la foto lo colocas en el listener el evento «canplay» del elemento «video». En este mismo evento colocas el código que detiene el video después de obtener la foto.

      De esta forma el usuario presiona un botón y automáticamente toma la foto.

  31. Tengo una pregunta Roimer, con tu código se puede acceder a la camara de un celular sin hacer ninguna modificación?

    • Hola Isaac, si: el jsfiddle que pude se ejemplo lo probé en mi teléfono con el navegador Android (4.2), Chrome y Firefox (no recuerdo las versiones). El único detalle es que sea cual sea el dispositivo usará «por defecto» la cámara que tenga establecida «por defecto» el dispositivo. En mi PC por ejemplo al principio me mostraba la capturadora de video (y podía ver la TV en mi página 🙂 ).

    • Saludos Alejandro, monté todo el código del artículo en un solo archivo y lo probé (solo cambié la referencia de jQuery para usar el CDN). Puedes ver el código completo aquí https://gist.github.com/roimergarcia/6e391021cf04902fb72b ; hay un botón de descarga en el panel de la derecha, o simplemente lo copias y pegas en un archivo html.
      Un solo detalle: debes probarlo en un servidor web (Apache, IIS…): si abres el archivo HTML directamente en el navegador no va a funcionar porque no se permite acceder al hardware si la URL de la página empieza por «file://». Si n tienes un servidor a mano prueba este http://www.uwamp.com/en/ es fácil de usar y no requiere instalación.

  32. Epa Roimer q tal..? una pregunta.. ¿Hay alguna manera de colocar el video de manera vertical? es q me toma la img con mas tamaño de ancho q de alto y la necesito tipo carnet intente modificar el tamaño al canvas donde se muestra la foto pero solo la coloca mas alta, osea la estira, y si cambio el w y h del video lo hace como si fuera un div pero pareciera q es el video q esta ya pre configurado a tomarla horizontalmente y la necesito vertical ps

    • Hola Juan! jeje, se que es bastante tarde pero igual te respondo 🙂 tienes dos opciones: una es que captures la foto tal y como está y le muestres al usuario un «rectángulo» sobre la foto para que el seleccione un área de la forma y tamaño que tu indiques (como cuando cambias tu foto de perfil en Facebook). La otra opción es que automáticamente «cortes» la foto en la medida/relación que quieres. En código estaría en el botón que toma la foro, debes cambiar esto:

      w = oCamara.width();
      h = oCamara.height();
      oFoto.attr({ 'width': w, 'height': h });
      oContexto = oFoto[0].getContext('2d');
      oContexto.drawImage(oCamara[0], 0,0,w, h);

      Por esto:

      w = oCamara.width();
      h = oCamara.height();
      w2 = w*(3/4);
      oFoto.attr({ 'width': w2, 'height': h });
      oContexto = oFoto[0].getContext('2d');
      oContexto.drawImage(oCamara[0], (w-w2)/2, 0, w2, h, 0,0,w2, h);

      Fijate que DrawImage se ejecuta con más parámetros. De este modo le decimos «copia el alto total del video, pero solo de ancho solo copia 3/4 de la altura (foto vertical) descartando lo que sobre por los lados, que será (w-w2)/2 de cada lado; luego pégalo en el canvas ocupando todo el espacio (que ya está recortado a la medida) »
      Mira este ejemplo actualizado: http://jsfiddle.net/roimergarcia/zv4tgeaa/ y me avisas si te sirvió (o si ya resolviste 🙂

  33. Hola buenos dias, muy interesante tu articulo, he leido y a nadie la ha pasado lo que a mi, pero una vez q me pide permiso para compartir la cámara me sale el error que no se puede tener acceso a la cámara, será por la distribución? yo tengo debian.
    Agredeceria mucho tu ayuda

  34. Hola, yo tengo una pregunta, el codigo me funciona bien pero al aplicarlo en un smartphone me selecciona es la camara de adentro es decir para auto-retratos como puedo hacer para que me seleccione la camara prinpipal

  35. Hola, interesante articulo….en jsfiddle funciona muy bien el codigo y ejemplo… pero trato de hacerlo funcionar de manera local y no funciona ninguno de los botones, no aparece error ni nada cual puede ser el problema?,

    • Alejandro! normalmente lo primero que falla es cuando lo abres en un navegador desde el sistema de archvos, pero si estás usando Apache entonces no es eso 🙂 lo siguiente sería verificar que estés cargando jQuery: en el jsFiddle estoy usando jQuery 1.8, pero descargado de forma automática: el código javascript se ejecuta en el DomReady (o «jQuery(document).ready»). Otra cosa a verificar es que realmente tengas la cámara disponible: trata de acceder a tu cámara con otro programa primero, si funciona entonces cierra el programa (para dejarla libre) e intenta de nuevo. Claro, cuando pruebes el còdigo manten el panel de depuraciòn del navegador abierto en todo momento para y fijate si tienes errores en el Javascript o en el panel de red. Comenta de nuevo por aquí si tienes problemas 🙂

  36. Hola Roimer me gustaría saber como puedo acceder a una camara web por ip y mostrarla en html5 para todos los navegadores

    • Hola Florentino, tu mensaje cayó a la carpeta de spam, y con lo complicado que estoy con el trabajo casi no la reviso :p mi email es roimergarcia (at) gmail.com aunque supongo que ya resolviste hace tiempo 🙂

  37. hola, no se si es que estoy haciendo algo mal porque he seguido tu tutorial y el resultado no es el esperado. Me explico, he montado mi propio servidor web y en la pagina he introducido tu codigo esperando que los clientes al conectarse viesen lo que emite mi webcam, pero no es asi, sino que lo que se les activa es su propia webcam. Si este es el funcionamiento correcto no le veo la utilidad, porque para que vale que se conecten a mi web y se vean ellos mismos en la pantalla a traves de su webcam, suponia que lo que verian seria mi propia webcam.

    Podrias decirme si es que he hecho algo ,mal.

    Un saludo

  38. Hola, estaba buscando un ejemplo asi hace tiempo, me parece un tuto genial, y voy a trabajar con ello, GRACIAS
    Una pregunta, sobre «el navegador probablemente muestre un mensaje al usuario indicándole que la página quiere tener acceso a la cámara web. El usuario puede aceptar o rechazar la petición, e incluso puede indicarle cuál “dispositivo” usar. Esto es útil si, por ejemplo, estás abriendo esta página desde tu móvil o tablet y este cuenta con dos cámaras (frontal y trasera).»

    He probado en el portatil y funciona perfecto, sin embargo en un samsung s4 con android kitkat 4.4.2, con navegador chrome (el nativo no lo soporta), aunque funciona, solo pregunta el permiso para utilizar la camara, y utiliza la camara frontal…

    tambien parece que la parte inferior de la foto (y video) queda en negro…

    La idea es hacer una foto a un codigo qr y descodificarlo, yo creo que tene que ser podible! me quedan horas de investigacion!, pero si supieras como forzar la camara trasera… o como al menos preguntarlo desde el mobil…

    gracias otra vez

  39. Me contesto a mi mismo,,, el navegador android no permite seleccionar la camara trasera, puede que con algún código en javascript se pueda hacer, pero resulta que en firefox si funciona, firefox para android! al pedir permiso para usar la camara puedes seleccionar camara delantera o trasera, asi que perfecto! 😉

  40. muy bueno el tutorial. alguien tiene el codigo para subir la imagen al servidor? se lo agradeceria de antemano.

  41. Hola se ve que esta todo bien explicado pero antes me gustaría saber si con esto puedo elegir o tener por predeterminado la cámara trasera de una tablet. Use el componente de Primefaces para tomar y guardar fotos en BD pero ahora que hago pruebas en la tablet me doy cuenta que está usa por defecto la camara frontal y necesito que use la trasera. Su ejemplo es la solución o como puedo lograr lo que quiero. Ayuda por fa’

  42. Recién leo los comentarios allí estaba lo que quería pero ya lo habia encontrado en otro lado. Igual vi una que otra cosa que me servirá pero lo malo es que han matado casi todas mis esperanzas respecto a evitar que chrome pregunte que camara usar.

    …(Lord, deja de joder con la misma cosa y «preguntando» de esa manera ¬¬ .i )

  43. Buenas, me sirvio muchisimo esto. Hay alguna forma de crear un botón que por ejemplo se llame : «Ver contenedores» y que al presionarlo me muestre los contenedores y los demas botones de Iniciar, Detener etc? Me refiero a una ventana con todo eso dentro, en forma de PopUp. Saludos!

    • Hola Leandro, disculpa lo taaarde :p jejeje
      Si, es sencillo: colocas todo dentro de un div con display:none. Luego en el botón «ver contenedores» le pones al div display: block; Ahora, para que sea un popup además del display debes centrar el div en pantalla y generalmente pones un fondo para que el usuario se enfoque en el popup. Aquí tienes un ejemplo simple http://jsfiddle.net/roimergarcia/wbxtywwj/

  44. Hola! Buenisima la guia, Tenes idea de como podria hacer para que al tocar stop, se guarde el video y se suba al servidor o a la propia pc? Gracias!

  45. Hola buen día, lo que pasa es que soy nueva en la parte de programación y pues soy practicante en una empresa y pues quisiera saber si sabes como hacer de que aparte de que tome la foto me la pueda guardar en una base de dato mysql?
    quedo atenta a tus comentarios

  46. lo que pasa es que tengo que hacer un programa en donde registre unos datos de un visitante y aparte de eso le tome una foto pero pues tengo todo el crud de los datos pero la verdad no se como meterle lo de la camara sin que me afecte el resto del codigo pues la verdad casi no soy buena hasta ahora estoy aprendiendo y me gustarí mucho si no hay molestia me explicaras :).

  47. perdón y todo lo estoy trabajando en php

    pues la verdad casi no se ve organizado en codigo pero esto es lo que tengo en el insert

  48. esta es la parte del insert pero no se como guardarla ni mucho menos consultarla 🙁 que pena tanta molestia pero estoy desesperada

    .contenedor{ width: 430px; float: left;}
    .titulo{ font-size: 10pt; font-weight: bold;}
    #camara, #foto{
    width: 200px;
    min-height: 100px;
    border: 5px solid #FF0000;
    float: right;

    }

    window.URL = window.URL || window.webkitURL;
    navigator.getUserMedia = navigator.getUserMedia
    || navigator.webkitGetUserMedia
    || navigator.mozGetUserMedia
    || navigator.msGetUserMedia
    || function(){alert(‘Su navegador no soporta navigator.getUserMedia().’);};

    jQuery(document).ready(function(){
    //Este objeto guardará algunos datos sobre la cámara
    window.datosVideo = {
    ‘StreamVideo’: null,
    ‘url’ : null
    };

    jQuery(‘#botonIniciar’).on(‘click’, function(e){
    //Pedimos al navegador que nos de acceso a
    //algún dispositivo de video (la webcam)
    navigator.getUserMedia({‘audio’:false, ‘video’:true}, function(streamVideo){
    datosVideo.StreamVideo = streamVideo;
    datosVideo.url = window.URL.createObjectURL(streamVideo);
    jQuery(‘#camara’).attr(‘src’, datosVideo.url);
    }, function(){
    alert(‘No fue posible obtener acceso a la cámara.’);
    });

    });

    jQuery(‘#botonDetener’).on(‘click’, function(e){
    if(datosVideo.StreamVideo){
    datosVideo.StreamVideo.stop();
    window.URL.revokeObjectURL(datosVideo.url);
    };
    });
    jQuery(‘#botonFoto’).on(‘click’, function(e){
    var oCamara,
    oFoto,
    oContexto,
    w, h;

    oCamara = jQuery(‘#camara’);
    oFoto = jQuery(‘#foto’);
    w = oCamara.width();
    h = oCamara.height();
    oFoto.attr({‘width’: w, ‘height’: h});
    oContexto = oFoto[0].getContext(‘2d’);
    oContexto.drawImage(oCamara[0], 0, 0, w, h);

    });
    });

    Iniciar
    Detener
    Foto

    Cámara

    Foto

    Ingresar Visitante

    Hora Ingreso:

    Hora Salida:

    Nombre:

    Apellido:

    Empresa:

    Funcionario a Visitar:

    Area:

    Portatil :

    Carro :

    Fecha:

    Vigilante que registra Entrada :

    Vigilante que registra Salida :

    aquí es donde guarda los datos :

    ejecutar($sql);

    echo «DATOS INSERTADOS CORRECTAMENTE»;

    ?>

    y ésta es la consulta:

    Consultar visitantes

    IdHora IngresoHora SalidaNombreApellidoEmpresaFuncionarioAreaPortatilCarroFechaVigilante De EntradaVigilante De Salida

    ejecutar($sql);

    /*Realizamos un bucle para ir obteniendo los resultados */

    while ($variables =$db->resultados($result)){
    echo ».$variables[‘id’]
    .».$variables[‘hora_entrada’]
    .».$variables[‘hora_salida’]
    .».$variables[‘nombre’]
    .».$variables[‘apellido’]
    .».$variables[‘empresa’]
    .».$variables[‘funcionario’]
    .».$variables[‘area’]
    .».$variables[‘portatil’]
    .».$variables[‘carro’]
    .».$variables[‘fecha’]
    .».$variables[‘nombre_vigilante’]
    .».$variables[‘vigilante_salida’].»;
    }

    ?>

    • Hola Jhoanna, el código se ve sin formato… ¿Cómo haces el post del formulario? los envías por AJAX o usas un botón tipo submit? Si es vía AJAX debes crear un objeto FormData (https://developer.mozilla.org/es/docs/Web/Guide/Usando_Objetos_FormData) y agregar un objeto Blob que contenga los bytes de la imagen (con la función «canvas.toBlob()» ). Luego en PHP lees la imagen como si fuera un archivo seleccionado por el usuario en un input[type:file]. Ahora, lo siguiente dependerá de si vas a guardar la imagen en una carpeta (y en la BD solo el nombre de la imagen) o si vas a insertar la imagen por completo en la BD (ojo: en general es preferible guardarla en disco, no en DB).

  49. Hola Roimer cómo estás, inicialmente felcitaciones y gracias por enselarnos. Hermano no he podido hacer trabajar tu código. Estoy haciendo un modulo en php para el registro de ingreso y/o salida de equipos, y quiero tomar una foto al momento de la salida y/o entrada, y:
    1. No he podido hacer funcionar tu código
    2. He implementado otros ejemplos y no funcionan bien.

    Sería de gran ayuda si me facilitas el código fuente completo para implementarlo, como te dije anteriormente hice el copie y pegue y no funciona.

  50. Hola Roimer de un abrazo fuerte, hermano ya me funciona el código, pero no logro hacer que guarde la imagen con nombre que yo quiero, por ejemplo entra pepito perea con cedula 222222, el numero de la cedula debe ser el nombre del archivo para poderlo bincular al usuario.

  51. Buenos días Roimer y David Cornejo, disculpenme la ignorancia, pero No se cómo guardar la foto tomada en un directorio en el servidor, por ejemplo, el Sr Pepito Perez, con cedula No. 123456, le tomo la foto de ingreso y necesito que la guarde con el Numero de Cedula ingresado. Hasta tomar la foto todo bien, pero para guardarla No Se como hacerlo, en Jqery hasta hoy leo sobre el, y en php no entiendo como pasar el nombre a la funcion que guarde ni como hacer que guarde. Por havor ayudenme, estoy embotellado y necesito resolver este inconveniente. Necesito hacer un boton que diga Guardar Foto.

    //code.jquery.com/jquery-1.8.3.js

    Prueba de cámara Web
    http://jquery-1.8.2.min.js
    http://camarajs.js
    //code.jquery.com/jquery-1.11.0.min.js

    Cámara

    Foto

    Y el código JS ya lo conocen… Yo cree una camara.js donde esta la función que llama la camara, detiene la camara y toma la foto. Ahora quiero que al llamar a camara.php (la de arriba) se active la camara automaticamente.

    • Hola PlutoElias, ya estoy de vuelta 🙂
      OK, hasta donde entiendo tienes la cámara funcionando y ya tomas la foto y la pones en el canvas. Lo que te falta es guardarla en el servidor. ¿enviarás la imagen (y los demás campos del form) mediante submit o con ajax? Si es con ajax lee mi comentario del 23/septiembre.
      Luego, en PHP (suponiendo que tu file input tiene name=»MiFoto» y el archivo se llama perfil.png):

      //Carpeta de salida y nombre para guardar la imagen:
      $codigo_usuario = $_POST[‘CodigoUsuario’]; //OJO: Debes sanitizar esto!!!
      $carpeta_fotos = ‘/var/www/uploads/’;
      //Te toca ver como tomar la extensión del nombre original: $_FILES[‘MiFoto’][‘name’]
      $fichero_subido = $carpeta_fotos . $codigo_usuario.’.png’;
      //Los archivos se suben a una carpeta temporal: lo sacas de allí y lo pones en tu carpeta
      if (move_uploaded_file($_FILES[‘MiFoto’][‘tmp_name’], $fichero_subido)) {
      // Todo bien 🙂
      } else {
      // Error 🙁
      }

      IMPORTANTE: no he probado este código, básicamente es un resumen de este: http://php.net/manual/es/features.file-upload.post-method.php

  52. Hola Roimer

    Antes que nada muchas gracias por tu código y felicitaciones es muy bueno, tengo una gran duda, sabrás como activar el flash de la cámara? estoy trabajando con una tableta que tiene flash.

    Espero me puedas orientar.

    Saludos.

    • Gracias a ti por comentar! Hasta donde sé el navegador no provee una API que permita controlar directamente la cámara desde una página web, lo que hacemos es pedirle un url que nos mande «lo que la cámara ve». Se que se puede hacer usando Javascript pero solo si estas programando una app con Cordoba u otra «carcasa» que al final te genera una app nativa.

  53. hoye amigo soy nuevo en esto tengo este codigo en la afterinicializate pero no me guarda nada
    $imagenB64 =$_POST[«cMiFoto»];
    $nombreArchivo=$_POST[«cNombreArchivo»];
    $imagenBytes=base64_decode($imagenB64);
    $destino=»images\».$nombreArchivo
    $imagenR=imagecreatefromstring($imagenBytes)
    imagepng($imagenR,$destino)

    • Saludos SancoSanco,

      El problema está después de esta línea (lo indiqué en uno de los comentarios 🙂 :
      $imagenB64 = $_POST[‘cMiFoto’]

      En ese punto, la variable $imagenB64 tiene un string que comienza por “data:image/png;base64,” (o “data:image/jpg;base64,” dependiendo del tipo de imagen). Esto lo tienes que «borrar» del string antes de convertir la cadena en imagen; además, los datos los estás enviando por POST, así que PHP asume que los signos de «+» representan espacios » » y te los cambia, por esto debes convertir de nuevo los espacios en «+» antes de crear la imagen. Quedaría así:

      $imagenB64 =$_POST[“cMiFoto”];
      $imagenB64 = substr(($imagenB64),strpos(($imagenB64),’,’)+1); //Separamos el contenido de la imagen
      $imagenB64 = str_replace(‘ ‘,’+’,$imagenB64); //reemplazamos los espacios en blanco por «+»
      $nombreArchivo=$_POST[“cNombreArchivo”];
      $imagenBytes=base64_decode($imagenB64); //ahora si podemos crear la imagen
      $destino=”images\”.$nombreArchivo
      $imagenR=imagecreatefromstring($imagenBytes)
      imagepng($imagenR,$destino)

      DISCLAIMER: no soy programador PHP, jejeje, yo trabajo en ASP, solo se lo suficiente como cualquier programador web 😉

Soluciones claras y simples



Ing. Industrial, dedicado a la programación en ASP.NET+VB, SQL y Javascript+AJAX; y un poco de Android, Kotling, y Unity 🙂
Valencia, Venezuela



¿QUIERES APOYARME?

¿Te ha sido de ayuda alguno de mis artículos? Generar contenido técnico requiere de tiempo y esfuerzo. Con tu colaboración me puedes ayudar a mantener mi blog activo y actualizado. Si quieres y puedes apoyarme has clic aquí:

https://paypal.me/roimergarcia


ENTRADAS RECIENTES