Quantcast
Channel: Planeta Código
Viewing all articles
Browse latest Browse all 2711

El blog de Adrián Arroyo: Programando el Chromecast desde JavaScript

$
0
0

Chromecast (o Google Cast) es un dongle, un pequeño aparato, que se conecta a una entrada HDMI y permite disfrutar de contenido multimedia a un precio bastante ajustado (35$). Oficialmente solo se puede programar usando los SDK de iOS, Android y Chrome pero la comunidad ha conseguido replicar el protocolo interno. Chromecast ha tenido varios protocolos de comunicación pero el importante para lo que vamos a realizar se llama CASTv2.

Chromecast

¿Cómo funciona Chromecast por dentro?

Primero voy a explicar como funciona el Chromecast. Chromecast sigue la filosofía de los Chromebooks, en el que todo el sistema es el navegador web, en este caso Chrome. Una app se conecta a Chromecast a través del protocolo de descubrimiento, deben estar en la misma red Wi-Fi. La aplicación solicita iniciar una aplicación, para lo cual manda el ID de la aplicación que desea abrir. Chromecast busca en la base de datos de Google (https://cast.google.com, tasa de registro de 5$) y allí le indicará una URL.

Chromecast abre la web y ejecuta la aplicación, que usando una librería de JavaScript le permite comunicarse con la app original. Podemos distinguir sin embargo varias aplicaciones “preinstaladas”. Son webs como el resto pero están alojadas por Google sin marca. Son DefaultMediaReceiver y StyledMediaReceiver. Se trata de dos reproductores multimedia básicos, que soportan vídeo en MP4 y WebM desde una URL, subtítulos, carátula y en el caso de StyledMediaReceiver es posible modificar un poco el aspecto del reproductor.

Esquema de Chromecast

Reproduciendo un vídeo con Chromecast, Node.js y DefaultMediaReceiver

Como hemos visto, reproducir un vídeo en Chromecast no es muy difícil. Para ello me voy a ayudar en la librería chromecast-js que en última instancia remite a node-castv2-client.

En un ordenador, dentro de la misma red Wi-Fi que el Chromecast y con Node.js instalado ejecutamos:

mkdir chromecast-video
cd chromecast-video
npm install chromecast-js

Creamos un archivo de JavaScript con el siguiente contenido

varchromecastjs=require('chromecast-js');// Obtenemos la libreríavarbrowser=newchromecastjs.Browser();// Iniciamos la búsquedabrowser.on('deviceOn',function(device){// Cuando encuentre un dispositivo...device.connect();// Nos conectamos a éldevice.on('connected',function(){// Y cuando nos conectemosdevice.play('http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4',60,function(){// Mandamos reproducir el vídeo Big Buck Bunny, en MP4, no desde el principio, sino desde el primer minutoconsole.log('Reproduciendo en el Chromecast!');});setTimeout(function(){// Pasados 30 segundos paramos el vídeodevice.pause(function(){console.log('Paused!')});},30000);setTimeout(function(){// Pasados otros 10 segundos más, se corta la retransmisióndevice.stop(function(){console.log('Stoped!')});},40000);})})

Es un ejemplo muy sencillo. Como veis, Chromecast se conecta directamente al vídeo que reproduce, el dispositivo de control solo es eso, solo controla, nunca envía la película.

Personalizando con StyledMediaReceiver

El módulo chromecast-js también permite usar el StyledMediaReceiver, cuyo funcionamiento es idéntico al de DefaultMediaReceiver pero se le puede personalizar el aspecto. Además añadimos subtítulos (formato WebVTT) y una carátula.

varchromecastjs=require('chromecast-js')varbrowser=newchromecastjs.Browser()varmedia={url:'http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4',// El vídeosubtitles:[{language:'en-US',url:'http://carlosguerrero.com/captions_styled.vtt',name:'English',},{language:'es-ES',url:'http://carlosguerrero.com/captions_styled_es.vtt',name:'Spanish',}],// Los subítulos, un fichero para inglés y otro para español, en formato WebVTTcover:{title:'Big Bug Bunny',url:'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg'// Carátula, se muestra cuando el vídeo se está cargando},subtitles_style:{backgroundColor:'#FFFFFFFF',// see http://dev.w3.org/csswg/css-color/#hex-notationforegroundColor:'#000FFFF',// see http://dev.w3.org/csswg/css-color/#hex-notationedgeType:'DROP_SHADOW',// can be: "NONE", "OUTLINE", "DROP_SHADOW", "RAISED", "DEPRESSED"edgeColor:'#AA00FFFF',// see http://dev.w3.org/csswg/css-color/#hex-notationfontScale:1.5,// transforms into "font-size: " + (fontScale*100) +"%"fontStyle:'BOLD_ITALIC',// can be: "NORMAL", "BOLD", "BOLD_ITALIC", "ITALIC",fontFamily:'Droid Sans',fontGenericFamily:'CURSIVE',// can be: "SANS_SERIF", "MONOSPACED_SANS_SERIF", "SERIF", "MONOSPACED_SERIF", "CASUAL", "CURSIVE", "SMALL_CAPITALS",windowColor:'#AA00FFFF',// see http://dev.w3.org/csswg/css-color/#hex-notationwindowRoundedCornerRadius:10,// radius in pxwindowType:'ROUNDED_CORNERS'// can be: "NONE", "NORMAL", "ROUNDED_CORNERS"}// Aquí creamos un estilo para los subtítulos, la notación es fácil si ya conoces CSS}browser.on('deviceOn',function(device){device.connect()device.on('connected',function(){// Iniciamos la retransmisión, pero esta vez enviamos más información al Chromecast, usaremos StyledMediaReceiverdevice.play(media,0,function(){console.log('Playing in your chromecast!')setTimeout(function(){console.log('subtitles off!')device.subtitlesOff(function(err,status){// Desactivamos los subtítulosif(err)console.log("error setting subtitles off...")console.log("subtitles removed.")});},20000);setTimeout(function(){console.log('subtitles on!')device.changeSubtitles(1,function(err,status){// Restablecemos los subtítulos, pero al Españolif(err)console.log("error restoring subtitles...")console.log("subtitles restored.")});},25000);setTimeout(function(){device.pause(function(){console.log('Paused!')});},30000);setTimeout(function(){device.unpause(function(){console.log('unpaused!')});},40000);setTimeout(function(){console.log('I ment English subtitles!')device.changeSubtitles(0,function(err,status){if(err)console.log("error restoring subtitles...")console.log("English subtitles restored.")});},45000);setTimeout(function(){console.log('Increasing subtitles size...')device.changeSubtitlesSize(10,function(err,status){// Cambiamos el tamaño de los subtítulosif(err)console.log("error increasing subtitles size...")console.log("subtitles size increased.")});},46000);setTimeout(function(){device.seek(30,function(){// Nos movemos dentro del vídeoconsole.log('seeking forward!')});},50000);setTimeout(function(){console.log('decreasing subtitles size...')device.changeSubtitlesSize(1,function(err,status){if(err)console.log("error...")console.log("subtitles size decreased.")});},60000);setTimeout(function(){device.pause(function(){console.log('Paused!')});},70000);setTimeout(function(){device.seek(30,function(){console.log('seeking forward!')});},80000);setTimeout(function(){device.seek(30,function(){console.log('seeking forward!')});},85000);setTimeout(function(){device.unpause(function(){console.log('unpaused!')});},90000);setTimeout(function(){device.seek(-30,function(){console.log('seeking backwards!')});},100000);setTimeout(function(){device.stop(function(){console.log('Stoped!')});},200000);})})}

En definitiva, para muchas aplicaciones este módulo es más que suficiente. En caso de que queramos llevar un juego a Chromecast la cosa se complica. Tenemos que programar una app del tipo CustomMediaReceiver en HTML5 y luego su cliente (en Node.js o usando las librerías oficiales de Google para Android, iOS y Chrome). Si os ha gustado esta entrada y queréis saber como realizar esto último, compartid y comentad, me gustaría saber que opináis al respecto y podéis darme ideas.


Viewing all articles
Browse latest Browse all 2711