Mi media center http://www.mimediacenter.info Ideas para llevar la experiencia multimedia al salón Tue, 07 Mar 2017 00:30:03 +0000 es-ES hourly 1 https://wordpress.org/?v=4.7.6 http://www.mimediacenter.info/wp-content/uploads/2016/01/cropped-logo-mi-mediacenter-32x32.png Mi media center http://www.mimediacenter.info 32 32 Cómo desinstalar totalmente un add-on en Kodi / XBMC http://www.mimediacenter.info/2016/02/03/como-desinstalar-totalmente-un-add-on-en-kodi-xbmc/ http://www.mimediacenter.info/2016/02/03/como-desinstalar-totalmente-un-add-on-en-kodi-xbmc/#comments Wed, 03 Feb 2016 12:18:48 +0000 http://www.mimediacenter.info/?p=1754 Hay más de un tutorial por ahí que describe cómo instalar un add-on en Kodi, en este mismo blog puedes encontrar una entrada describiendo cómo instalar un add-on oficial, desde el repositorio de Kodi, o cómo instalar un add-on no oficial a partir de un fichero ZIP.

En realidad instalar un add-on no requiere más que descomprimir el fichero ZIP en el directorio add-ons, y si tiene la estructura correcta reinicias Kodi y aparecerá.

Pero ¿cómo podemos desinstalar un add-on una vez que ha sido instalado? ¿Completamente?


Primer paso: Desinstala el add-on desde Kodi

Kodi tiene una opción para desinstalar cualquier add-on que hayas instalado previamente, aunque está un poco escondida es muy sencilla y cumple con su función que es hacer desaparecer el add-on.

En primer lugar elige la opción “Sistema” en el menú principal:

Cómo desinstalar un add-on en Kodi (paso 1)

Ahora elige la opción “Add-ons”:

Como desinstalar un add-on en Kodi (paso 2)

Elige la opción “Mis add-ons”:

Como desinstalar un add-on en Kodi (paso 3)

Y elige el tipo de add-on que quieres desinstalar. Si eliges “Todos” te saldrá una lista, sorprendentemente extensa ya que Kodi tiene una buena parte de su funcionalidad básica implementada como add-ons.

Como desinstalar un add-on en Kodi (paso 4)

Elige ahora el add-on que quieres desinstalar:

Como desinstalar un add-on en Kodi (paso 5)

Utilizando el botón del menú contextual (tecla “C”) para abrir las opciones, elige “Información del add-on”:

Como desinstalar un add-on en Kodi (paso 6)

Y entre todas las opciones que te presenta Kodi elige “Desinstalar” para eliminar el add-on completamente.

Como desinstalar un add-on en Kodi (paso 7)

Segundo paso: Borrar el directorio en userdata/addon-data

La desinstalación desde Kodi elimina el add-on en el directorio de instalación “addons”, pero no elimina los parámetros de configuración y ficheros temporales que el add-on haya podido crear. Esto significa que si vuelves a instalar el add-on, seguirá conservando tu configuración, incluyendo las contraseñas que hayas podido poner.

Para eliminar estas configuraciones residuales del add-on tienes que eliminar todo rastro del add-on del directorio “userdata/addon_data”.

En primer lugar debes encontrar el directorio “userdata”, que es uno de los que Kodi crea en la ruta de datos. Si no sabes cómo encontrar la ruta de datos, puedes apoyarte de esta entrada que publiqué el otro día describiendo dónde estan las rutas de Kodi en todos los dispositivos que conozco.

Como saber la ruta donde está instalado XBMC / Kodi en tu dispositivo (multiplataforma)

Luego debes conocer el nombre interno de tu add-on. No hay una regla fija para esto, pero los add-ons suelen tener siempre nombres bastante claros. Se llaman “plugin.video.xxx”, “plugin.audio.xxx” donde “xxx” es lógicamente el nombre de tu add-on. Por ejemplo: “plugin.video.pelisalacarta”.

kodi-directorio-addon_data-en-userdata

Si encuentras un directorio dentro de userdata/addon_data con el nombre de tu add-on, bórralo. De esa forma desaparecerá cualquier configuración que tuvieras.

Tercer paso (y último): Borrar el fichero en el directorio “packages”

Cuando instalas un add-on desde un repositorio, lo que hace Kodi es descargar el fichero ZIP del add-on en el directorio “addons/packages” y luego instalarlo. Esto no ocurre cuando haces la instalación desde un archivo ZIP, es sólo cuando lo haces desde un repositorio.

kodi-directorio-packages-en-addons

Si no borras ese fichero, al volver a instalar la misma versión del add-on lo que harás realmente es volver a instalar el mismo fichero que descargaste previamente.

Así que vete a tu directorio “addons/packages” dentro de la ruta de datos de Kodi, busca un fichero con el nombre del add-on que quieras desinstalar, y si lo encuentras bórralo.

]]>
http://www.mimediacenter.info/2016/02/03/como-desinstalar-totalmente-un-add-on-en-kodi-xbmc/feed/ 10
Como saber la ruta donde está instalado XBMC / Kodi en tu dispositivo (multiplataforma) http://www.mimediacenter.info/2016/01/20/como-saber-la-ruta-donde-esta-instalado-kodi-en-tu-dispositivo-multiplataforma/ http://www.mimediacenter.info/2016/01/20/como-saber-la-ruta-donde-esta-instalado-kodi-en-tu-dispositivo-multiplataforma/#comments Wed, 20 Jan 2016 15:08:23 +0000 http://www.mimediacenter.info/?p=1766 Cuando le explicas a alguien cómo hacer una cosa en Kodi, normalmente en forma de una serie de pasos sencillos, siempre te queda la duda de si alguno de los pasos es realmente sencillo para todo el mundo.

Una de esas cosas básicas que das por sentado, pero que muchas veces causa confusión, es cómo conocer la ruta donde está instalado Kodi en tu dispositivo. En este tutorial vamos a ver diferentes dispositivos y la ruta donde puedes encontrar los ficheros de Kodi en cada uno.

Debes tener en cuenta que una instalación de Kodi siempre tiene dos directorios separados:

1) Directorio de la aplicación: En este directorio está el ejecutable de Kodi con sus componentes fundamentales, como el skin Confluence y las librerías de reproducción de vídeo. Normalmente no debes modificar nada aquí salvo que quieras actualizar alguno de ellos, aunque en ocasiones sí que viene bien consultarlo para ver cómo están hechos.

2) Directorio de datos: Es el directorio donde se instalarán los add-ons, donde está el directorio de datos del usuario (llamado userdata), donde se crean las bases de datos de la biblioteca y las imágenes, donde encontrarás los logs, etc. Lo más probable es que sea este directorio el que estás buscando.

Dicho esto, vamos a ver cómo localizar este directorio según el dispositivo que tengas:


Windows

En Windows es sorprendentemente difícil encontrar el directorio de datos, aunque no es igual con el directorio de la aplicación ya que está en el mismo sitio que el resto de aplicaciones. Donde uno podría esperar encontrarlo.

Todo depende de la versión de Windows que tengas, aquí van las opciones:

  • Aplicación (Windows 64 bits): C:\Program Files (x86)\Kodi\
  • Aplicación (Windows 32 bits): C:\Program Files\Kodi\
  • Aplicación (Windows XP): C:\Archivos de programa\Kodi\
  • Datos (Windows 7 y posteriores): C:\Users\tunombredeusuario\AppData\Roaming\Kodi
  • Datos (Windows XP): C:\Documents and settings\tunombredeusuario\AppData\Roaming\Kodi

También puedes encontrar el directorio de datos si pulsas en “Inicio”, “Ejecutar” y tecleas “%APPDATA%\kodi\userdata”. El explorador de archivos de Windows se abrirá en ese directorio.

Mac OS X

La aplicación en Mac OS X se instala como el resto de aplicaciones, y luego crea los directorios de trabajo en tu directorio de usuario. Bastante estándar.

  • Aplicación: /Applications/Kodi.app/Contents/Resources/Kodi
  • Datos: /Users/tunombredeusario/Library/Application Support/Kodi

Linux

Las distribuciones de Linux pueden ser algo variables a la hora de ubicar el directorio de aplicación, por lo que al final depende de cuál estés usando, pero el directorio de datos suele estar siempre en el mismo sitio:

  • Aplicación (Ubuntu): /usr/share/kodi
  • Datos: /home/tunombredeusuario/.kodi

Android

Puesto que Android tiene una base open source, y cada fabricante es libre de adaptarlo a sus necesidades, puedes encontrar también bastante variación a la hora de localizar los directorios de instalación de aplicaciones.

La clave es encontrar el directorio “data”, que puede cambiar de ubicación de un dispositivo a otro.

Prueba primero con /sdcard/Android/data, el más habitual, pero sin no tienes suerte puedes probar también con /storage/Android/data, o /data/data.

Una vez que tengas localizado el directorio “data”, es más fácil:

  • Aplicación: data/org.xbmc.kodi/files
  • Datos: data/org.xbmc.kodi/files/.kodi

iOS

A pesar de que la estructura de ficheros de iOS está basado tanto en Linux como en Mac OS X, puedes encontrar diferencias según estemos hablando del venerable Applet TV 2 (con XBMC y no Kodi), o de una versión de iOS más moderna.

  • Aplicación en Apple TV 2: /private/var/stash/Applications/XBMC.frappliance/XBMCData/XBMCHome/
  • Aplicación en otros dispositivos iOS: /Applications/Kodi.app/
  • Datos: /private/var/mobile/Library/Preferences/Kodi

OpenElec

Como OpenElec es una distribución de Linux basada específicamente en Kodi, y por otra parte alejada de otras distribuciones populares como Ubuntu, tiene algunas peculiaridades.

Por ejemplo el directorio de aplicación es de sólo lectura (no puedes modificarlo), probablemente por motivos de rendimiento, y encontrarás que todo lo que puede ser modificado se monta en la ruta /storage en lugar de ser un directorio dependiente del usuario.

Eso nos deja con estos dos directorios:

  • Aplicación: /usr/share/kodi/
  • Datos: /storage/.kodi

Raspbmc / OSMC

Si tienes una Raspberry y no te gusta OpenElec lo más probable es que hayas optado por Raspbmc, o el más reciente proyecto de su mismo autor llamado OSMC. En ambos casos las rutas coinciden:

  • Aplicación: /home/pi/.xbmc-current/xbmc-bcm/xbmc-bin/share/xbmc
  • Datos: /home/pi/.xbmc

Xbian

Esta distribución de Linux para Raspberry tiene una filosofía distinta de las anteriores, buscando estar más al día con las últimas versiones de cosas en lugar de primar la estabilidad como las anteriores.

  • Aplicación: /usr/share/kodi
  • Datos: /home/xbian/.xbmc

Enigma 2

Las nuevas distribuciones de Enigma 2 para los dispositivos VU+ Solo, VU+ Solo 2 y VU+ Duo 2 tienen una versión de XBMC disponible, y según la imagen también puedes encontrar Kodi.

  • Aplicación:
  • Datos (si usas disco duro): /media/hdd/.kodi/
  • Datos (si usas pendrive): /media/usb/.kodi/
  • Datos (resto de casos): /home/root/.kodi/

¿Me dejo alguna?

Aunque en un momento u otro he acabado usando todos estos dispositivos, esta entrada me ha supuesto un buen rato de pruebas, buscar en Google y un par de preguntas hechas a las personas adecuadas.

Si encuentras algún error, o echas en falta algún dispositivo que requiera un detalle especial, te agradeceré que dejes un comentario para que pueda mejorar esta entrada.

]]>
http://www.mimediacenter.info/2016/01/20/como-saber-la-ruta-donde-esta-instalado-kodi-en-tu-dispositivo-multiplataforma/feed/ 2
Cómo saber la dirección IP de tu media center en XBMC / Kodi http://www.mimediacenter.info/2016/01/11/como-saber-la-direccion-ip-de-tu-media-center-en-kodi/ http://www.mimediacenter.info/2016/01/11/como-saber-la-direccion-ip-de-tu-media-center-en-kodi/#respond Mon, 11 Jan 2016 14:58:40 +0000 http://www.mimediacenter.info/?p=1579 Hablando en el contexto de los media centers, la dirección IP es un identificador único que tu router asigna a cada uno de los dispositivos que tienes conectados. Seguro que lo has visto otras veces, es una secuencia de 4 números separados por puntos donde en la mayoría de los casos los dos primeros son 192.168:

192.168.1.35
192.168.2.40

Tarde o temprano en tu media center necesitarás hacer una operación que te requiera conocer la dirección IP del dispositivo. Ya sea conectarte por SSH con un terminal, copiar ficheros, etc.

Aunque la forma de consultar la direccion IP es diferente segun el dispositivo y el sistema que tenga instalado, lo que a veces es un poco lio, en los dispositivos donde tienes instalado Kodi tienes un recurso muy sencillo para conocer tu dirección IP ya que independientemente de la plataforma siempre muestra la información en el mismo sitio.

Sólo tienes que seguir los pasos.


1) En el menú principal de Kodi mueve la selección hasta la opción “Sistema”, pero no la selecciones porque lo que te interesa está en el pequeño menú inferior.

Cómo averiguar la IP de tu media center Kodi

2) Vete hacia abajo con los cursores, y elige el menu “Info del sistema”.

Cómo averiguar la IP de tu media center Kodi

3) En el resumen que aparece inmediatamente despues puedes ver informacion basica, que incluye la direccion IP, o puedes elegir la pestaña “red” para tener informacion mas detallada.

Cómo averiguar la IP desde tu media center Kodi

Si tu dispositivo tiene una dirección fija puedes apuntarla, de lo contrario no es extraño que esta dirección cambie después de reiniciar el router o el dispositivo. Aunque resulta muy fácil consultarla cuando la necesites.

]]>
http://www.mimediacenter.info/2016/01/11/como-saber-la-direccion-ip-de-tu-media-center-en-kodi/feed/ 0
Cómo transferir ficheros a tu media center Raspberry Pi http://www.mimediacenter.info/2014/02/23/como-transferir-ficheros-a-tu-media-center-raspberry-pi/ http://www.mimediacenter.info/2014/02/23/como-transferir-ficheros-a-tu-media-center-raspberry-pi/#comments Sun, 23 Feb 2014 17:12:34 +0000 http://www.mimediacenter.info/?p=1502 Si tienes una Raspberry Pi como mediacenter hay muchas formas de transferir ficheros desde tu ordenador, independientemente de que uses Raspbmc, OpenElec, XBian o incluso Raspbian.

La razón es que estos dispositivos funcionan gracias a distribuciones Linux que incluyen sistemas muy completos de carpetas compartidas (Samba), FTP y SSH.

De todas las opciones yo siempre he encontrado que la más cómoda es usar SSH, ya que viene instalado de serie en todas las distribuciones (que yo sepa) y sólo necesitas conocer la IP del dispositivo. No hay que hacer ningún paso más de configuración en tu Raspberry antes de intentarlo.

Si quieres copiar un add-on para instalarlo, copiar un vídeo para verlo localmente en tu Raspberry, o modificar algún fichero de configuración, aquí tienes la secuencia de pasos.


1) Averigua la IP de tu Raspberry

Lo primero que necesitas es conocer la dirección de tu Raspberry dentro de tu red.

Como es un procedimiento sencillo, al menos cuando estás dentro de Kodi, pero en muchas ocasiones lleva a confusión a los usuarios menus experimentados, he optado por hacer un breve tutorial con todas las imágenes paso a paso. Así no habrá dudas.

Sigue este enlace para ver cómo averiguar la dirección IP desde XBMC / Kodi.

Cómo averiguar la IP desde tu media center Kodi

2) Conéctate usando Filezilla

Una vez que tengas la IP necesitas un programa para hacer la copia en sí.

Hay muchos programas que permiten hacer transferencias de ficheros, pero si quieres tener el mejor y prefieres no gastarte dinero yo te recomiendo Filezilla. Es una de esas pequeñas joyas que tienes disponible los principales sistemas operativos (Windows, Linux y Mac) así que es difícil equivocarte.

Hay 4 parámetros que tienes que darle a FileZilla para establecer la conexión:

Parámetros de conexión con Filezilla

  • Servidor: Pon aquí la IP de tu Raspberry, por ejemplo 192.168.2.31
  • Nombre de usuario: En Raspbmc y Raspbian es “pi”, en OpenElec y XBian es “root”.
  • Contraseña: En Raspbmc, Raspbian y XBian es “raspberry”, en OpenElec es “openelec”.
  • Puerto: 22 (si no pones nada intentará conectarse en el puerto 21, que es el FTP)

Luego pulsa en el botón “Quickconnect” para establecer la conexión, y si todo ha ido bien tendrás dos zonas en la parte inferior que representarán tu ordenador (a la izquierda) y el dispositivo al que te has conectado (a la derecha).

Ficheros locales y remotos en Filezilla

3) Listo para transferir

Puedes moverte por los directorios a la izquierda y a la derecha, para elegir el origen y el destino de la transferencia, y una vez que hayas encontrado el fichero basta con que hagas doble click para transferirlo.

Si sabes la ruta también puedes escribirla en la caja donde pone “Local site” y “Remote site”, a veces es más sencillo.

La estructura de directorios de tu Raspberry también varía de una distribución a otra, pero todas tienen un directorio en el que están los datos de usuario de Kodi. Ese será el sitio donde tendrás que buscar los directorios de los add-ons, ficheros de configuración, etc.

  • Raspbmc: /home/pi/.xbmc ó /home/pi/.kodi
  • Raspbian: /home/pi/.xbmc ó /home/pi/.kodi
  • XBian: /home/xbian/.xbmc ó /home/xbian/.kodi
  • OpenElec: /storage/.xbmc ó /storage/.kodi

Para otros dispositivos puedes consultar esta entrada con la recopilación de diferentes ubicaciones de los directorios de Kodi.

Sencillo ¿no?

]]>
http://www.mimediacenter.info/2014/02/23/como-transferir-ficheros-a-tu-media-center-raspberry-pi/feed/ 5
Como programar add-ons en XBMC / Kodi: Mejorando la presentación http://www.mimediacenter.info/2013/08/28/como-programar-add-ons-en-xbmc-mejorando-la-presentacion/ http://www.mimediacenter.info/2013/08/28/como-programar-add-ons-en-xbmc-mejorando-la-presentacion/#comments Wed, 28 Aug 2013 17:22:51 +0000 http://www.mimediacenter.info/?p=1169 Si has seguido esta serie de tutoriales hasta aquí ya puedes programar tus propios add-ons, capaces de rivalizar con cualquiera de los que hay en el repositorio oficial de XBMC. Pero si te instalas unos cuantos y te pones a probar te encontrarás algunas sorpresas.

La entrada de hoy cuenta cómo puedes personalizar lo que tu add-on muestra al usuario, pasando de una simple lista plana de elementos a una presentación mucho más elaborada.

XBMC tiene algunas opciones interesantes para esto, que van desde usar colores en los items, especificar la duración o la calidad del vídeo, e incluso habilitar las vistas de “biblioteca” que suelen ser mucho más elaboradas para los items que tienen más información.


Formatos extendidos para los items

De forma similar a lo que haces en HTML, cuando muestras un texto en XBMC tienes la posibilidad de añadir tags que modifiquen el formato para diferenciar unos items de otros o para resaltar partes del texto.

Para ello puedes usar los tags que aparecen detallados en la wiki de XBMC, que incluyen desde la sintaxis de negritas:

Texto en [B]negrita[/B]

y cursivas:

Texto en [I]cursiva[/I]

Hasta el más habitual (y a menudo abusado) uso de los colores.

Ejemplo en [COLOR red]rojo[/COLOR] o [COLOR blue]azul[/COLOR]

Ojo porque en ambos casos las mayúsculas y minúsculas son importantes. Veamos cómo queda en XBMC:

plugintools.add_item(title="Texto en [B]negrita[/B]")
plugintools.add_item(title="Texto en [I]cursiva[/I]")
plugintools.add_item(title="Ejemplo en [COLOR red]rojo[/COLOR] o [COLOR blue]azul[/COLOR]")

Información extendida: Los InfoLabels

Puesto que XBMC está diseñado para reproducir archivos multimedia, y los items que añadas a la lista suelen consistir en vídeos, música o fotografías (aunque puedan ser otras cosas), hay una forma de darle más información sobre el archivo para que la utilice en la presentación. Es lo que suele llamarse “metadatos”, y en XBMC tiene el curioso nombre de InfoLabels.

En los ejemplos anteriores hemos visto cómo añadir el argumento o la imagen asociada, algo que se informa fácilmente usando los parámetros “title” y “thumbnail” de la función “add_item” de PluginTools.

Hay algunos elementos que no habíamos descrito, y que he añadido en la última versión de PluginTools, como el fanart que XBMC muestra cuando tienes seleccionado el item:

plugintools.add_item( title="Ejemplo con fanart", fanart="art.jpg")

Otro ejemplo sencillo de metadatos adicionales es “Duration” para especificar la duración del vídeo, que en el skin Confluence se muestra alineado a la derecha del nombre del item. Por una de esas cosas incomprensibles sólo puedes indicarle minutos, así que no podrás poner duraciones de menos de un minuto (una duración de 1 aparece como “1:00”) y las duraciones de más de una hora hay que indicarla con valores por encima de 60 (una duración de 90 minutos se pintarán como “1:30:00”).

La forma de especificar estos InfoLabels es añadirlos en un diccionario de Python a la función “add_item” en un parámetro opcional llamado “info_labels”.

plugintools.add_item(title="Ejemplo con duración",info_labels={ "Duration" : "23" }, folder=False)

También puedes especificar cosas más exóticas, como el género del vídeo, la productora, o la calidad. Son datos que cada skin explota de una forma u otra, según la vista que elijas. La lista completa de InfoLabels está en la wiki de XBMC.

Vistas extendidas

Si usas habitualmente el plugin de YouTube te habrás fijado en que al entrar en una lista de vídeos con el skin Confluence, la vista cambia automáticamente para mostrar la vista de “Thumbnails”.

Este truco tiene su complejidad. Aunque es fácil decirle a XBMC que cambie la vista por defecto, debes indicarle el código interno de la vista y es algo que cambia de un skin a otro. Si bien la vista de thumbnails es bastante popular, y suele corresponder con el código “500” en muchos skins, no es una regla fija.

Para simplificarlo tienes una función en PluginTools llamada “set_view” que acepta como parámetro un código genérico para cada tipo de vista. Puedes usar cualquiera de estos valores:

  • plugintools.LIST: Muestra el modo “lista” donde los elementos aparecen uno debajo de otro, y el thumbnail al lado.
  • plugintools.THUMBNAIL: Muestra el modo “thumbnail” donde los elementos aparecen como un mosaico de thumbnails con el título debajo, muy útil por ejemplo para hacer los menús de navegación.
  • plugintools.MOVIES: Muestra la lista de items como si fueran películas, utilizando una de las vistas de películas del skin que el usuario tenga instalado.
  • plugintools.TV_SHOWS: Muestra la lista como una lista de series, utilizando como antes una de las vistas disponibles en el skin del usuario.
  • plugintools.EPISODES: Complementando la anterior, muestra la lista de items como una serie de episodios.
  • plugintools.OTHER: Es el tipo de vista que te permite especificar directamente el código interno, según el skin que tenga el usuario.

Esto resulta muy cómodo ya que puedes elegir forzar la vista de lista o de thumbnails independientemente del skin, y también puedes forzar la vista de películas, series o episodios de forma explícita.

Por ejemplo mostrar una pantalla con películas puedes conseguirlo poniendo la vista a “plugintools.MOVIES” con la función “set_view”, y luego añadiendo los items con su argumento, thumbnail y fanart.

plugintools.set_view(plugintools.MOVIES)
plugintools.add_item(action="play",title="Oblivion",plot="...",thumbnail="http://...",fanart="http://...") 
plugintools.add_item(action="play",title="Transformers",plot="...",thumbnail="http://...",fanart="http://...") 
plugintools.add_item(action="play",title="Tron Legacy",plot="...",thumbnail="http://...",fanart="http://...")

En esta pantalla puedes ver cómo quedaría usando el skin Confluence:

Y aquí puedes ver cómo quedaría usando el skin Quartz:

Si la vista que te gusta no es la que PluginTools elige para tu skin puedes modificar el módulo plugintools.py para cambiarlo (verás que hay una lista al principio con los skins y el código de cada vista). O también puedes usar directamente la función set_view de PluginTools para especificar el código directamente.

plugintools.set_view(plugintools.OTHER,234)

Averiguar el código de vista de un skin no es sencillo, la verdad. Tendrás que abrir el código del skin y buscarlo manualmente.

A continuación

Hasta ahora hemos visto add-ons de vídeo, así que en la próxima entrada veremos cómo programar un add-on de otro tipo como música o fotografía. La mayoría de los conceptos siguen siendo válidos, teniendo en cuenta un par de diferencias y con los conocimientos adquiridos hasta aquí podrás desarrollar fácilmente estos nuevos tipos de add-ons.

]]>
http://www.mimediacenter.info/2013/08/28/como-programar-add-ons-en-xbmc-mejorando-la-presentacion/feed/ 1
Como programar add-ons en XBMC / Kodi: Leyendo datos de fuentes complicadas (continuación) http://www.mimediacenter.info/2013/04/30/como-programar-add-ons-en-xbmc-leyendo-datos-de-fuentes-complicadas-continuacion/ http://www.mimediacenter.info/2013/04/30/como-programar-add-ons-en-xbmc-leyendo-datos-de-fuentes-complicadas-continuacion/#comments Tue, 30 Apr 2013 00:33:43 +0000 http://www.mimediacenter.info/?p=1378 Continuando con la entrada de ayer, y hablando sobre cómo leer datos de sitios web que presentan alguna dificultad especial, hoy voy a detenerme un poco en los pasos necesarios para acceder a sitios protegidos mediante usuario y contraseña.

Es bastante habitual encontrarse sitios web que requieren un login o identificación, como los foros que ocultan los enlaces si no tienes cuenta, los sitios tipo red social como Series.ly donde los usuarios escriben y aporta, o incluso los sitios web privados a los que sólo se puede acceder mediante invitación.

En realidad el problema del login es muy sencillo de resolver, ya que el truco está en mantener una sesión en el sitio web y eso se consigue mediante cookies. La función read_body_and_headers de PluginTools soporta cookies, así que esto va a ser fácil.


Paso 1: Usar Firebug para ver cómo funciona el login

Un gran principio universal es que hay que utilizar la herramienta apropiada a cada problema, y para desarrollar plugins la herramienta es el navegador Firefox con el plugin Firebug instalado.

Este plugin tiene muchas funciones, pero la que necesitamos ahora es la pestaña de “Red” donde se graba la conversación entre el navegador y el sitio web. Con ambos instalados vamos a acceder a la web de mega-spain.com para entender cómo funciona el proceso de login.

Abre la URL de Mega-Spain en Firefox y pulsa sobre el botón “Visitante” que hay en la esquina superior derecha. Rellena los datos en el formulario de login pero no le des todavía al botón “Ingresar”.

Preparado para el login

Pulsa en el icono de la cucaracha de Firebug para abrirlo en la zona inferior de la pantalla.

Abriendo Firebug para la grabacion

Selecciona ahora la pestaña de “Red” en Firebug, pulsa en “Limpiar” en caso de que hubiera algo grabado previamente y pulsa el botón “Ingresar” para que haga el login.

La petición que hagas, la respuesta que obtengas y todos los elementos necesarios para pintarla (imágenes, scripts, estilos, etc.) quedarán grabados por Firebug.

Grabación realizada

Fíjate en que la primera línea es la del envío del login, se trata de un envío POST a una URL.

Detalle de la línea que contiene el login

Si pulsas en la pestaña “Post” verás exactamente lo que has enviado. La sección “Fuente” recoge el valor además tal como se ha enviado, justo lo que necesitamos.

Detalle del formato en que se envía el login

Así que para hacer el login tenemos que enviar a la URL “http://www.mega-spain.com/index.php?action=login2” una petición POST indicando en el cuerpo los valores “user=tvalacarta&passwrd=accede”. Fácil ¿no?

Paso 2: Activar las cookies

De la información que ha grabado Firebug podemos extraer dos detalles adicionales que son importantes.

El primero es que la respuesta a nuestro envío POST incluye la cabecera “Set-Cookie”, mediante la cual el servidor web indica al navegador que debe almacenar una cookie.

Cabeceras de envío del login

Esta cookie será enviada automáticamente por el navegador en sucesivas peticiones, y es precisamente lo que el servidor utiliza para relacionar todas las peticiones que recibe como pertenecientes a un mismo usuario. Esto lo hará PluginTools por tí exactamente igual que un navegador, ya que la función read_body_and_headers mantiene las cookies en un fichero en disco y las actualiza en cada petición.

Otro detalle importante es que la respuesta incluye una cabecera “Location”, que es una redirección mediante la que el servidor indica al navegador que debe saltar a una dirección distinta. Fíjate que Firefox hace el salto de forma automática, y cuando llames a read_body_and_headers se hará lo mismo a menos que indiques que no se sigan las redirecciones.

Paso 3: Enviar la información de login

Recopilando toda la información que hemos encontrado gracias a Firebug, concluimos que la forma de hacer el login por código es poner al principio de tu plugin estas líneas:

custom_post="user=tvalacarta&passwrd=accede"
body,response_headers = plugintools.read_body_and_headers("http://www.mega-spain.com", post=custom_post)

Tampoco ha resultado tan difícil, ¿no?

Cuando hayas ejecutado estas líneas, las cookies de la sesión se cargarán en el almacén de cookies de cada usuario. Todas las llamadas que se hagan a partir de ahí serán interpretadas por el servidor como si las hubiera realizado el usuario identificado.

Tratar las redirecciones manualmente

Resuelto el problema del login, hay un par de trucos más que es conveniente aprender para tener a mano cuando hacen falta. El primero de ellos tiene relación con la cabecera “Location” que hemos visto más arriba.

El comportamiento por defecto de un navegador es hacer una petición, y si la respuesta incluye una cabecera “Location” se usa la URL que especifica la cabecera como nueva dirección de salto.

En ocasiones es conveniente utilizar directamente la URL que se indica en la cabecera Location, y para eso basta con indicar el parámetro “follow_redirects” a False.

body,response_headers = plugintools.read_body_and_headers("http://www.mimediacenter.info", follow_redirects=False)

Lo más normal es que el cuerpo de la respuesta venga vacío, pero lo que te interesa es la cabecera así que tendrás que recorrer la lista de cabeceras de la respuesta:

location=""
for name,value in response_headers:
    if name=="location":
        location=value

Fíjate en que el nombre de la cabecera va en minúsculas.

Aumentar el timeout cuando el sitio web es lento

El último parámetro que queda por ver en la función “read_body_and_headers” te permite especificar un valor de timeout superior al que viene por defecto en tu intérprete de Python.

Es un problema habitual en los scripts de Python que se produzcan problemas debido a un timeout muy pequeño, lo que hace que algunas llamadas remotas fallen cuando de otra forma podrían haber funcionado.

Basta poner un valor de timeout suficientemente alto (en segundos) para que las llamadas remotas tengan más paciencia.

body,response_headers = plugintools.read_body_and_headers("http://www.mimediacenter.info", timeout=30*60)

Si el servidor es rápido el timeout no tiene ninguna influencia en el resultado, pero un timeout muy alto hará que la aplicación se quede bloqueada esperando.

Activar información de log ampliada

Cuando tienes que hacer cosas avanzadas es bueno ver exactamente el tipo de información que se envía y obtiene en cada petición, de forma que puedas entender por qué acabas teniendo el resultado que esperas.

En caso de que lo necesites puedes aumentar el nivel de detalle que se muestra en el log con dos variables que encontrarás en las primeras líneas del código fuente del módulo plugintools.py.

module_log_enabled = False
http_debug_log_enabled = False

Si pones la primera variable module_log_enabled a True, conseguirás que las funciones de PluginTools muestren información de depuración en el log. Todas las funciones escribirán en el log su nombre al ser invocadas, y la información relevante en cada caso como resultado de su ejecución.

La segunda variable http_debug_log_enabled puesta a True activa el log de depuración del módulo de Python urllib2, lo que te permitirá ver en el log todas las cabeceras HTTP.

Mucha información, pero en ocasiones imprescindible. No olvides desactivarla cuando vayas a usar tu plugin en el día a día, el fichero de log puede hacerse enorme.

Próxima entrada

Con esta entrada estamos llegando ya a la recta final de esta serie de tutoriales. En la próxima entrada veremos cómo utilizar metadatos extendidos en la lista de items. Eso nos permitirá especificar colores, negritas, duración de los vídeos, etc.

]]>
http://www.mimediacenter.info/2013/04/30/como-programar-add-ons-en-xbmc-leyendo-datos-de-fuentes-complicadas-continuacion/feed/ 6
Como programar add-ons en XBMC / Kodi: Leyendo datos de fuentes complicadas http://www.mimediacenter.info/2013/04/28/como-programar-add-ons-en-xbmc-leyendo-datos-de-fuentes-complicadas/ http://www.mimediacenter.info/2013/04/28/como-programar-add-ons-en-xbmc-leyendo-datos-de-fuentes-complicadas/#comments Sun, 28 Apr 2013 07:36:21 +0000 http://www.mimediacenter.info/?p=1167 Después de una interrupción de tres meses (increíble cómo pasa el tiempo), por fin he encontrado un hueco para continuar los tutoriales de programación de add-ons abordando algunos de los problemas que te encontrarás cuando programes add-ons en el mundo real.

Y es que no todos los sitios web son sencillos cuando quieres acceder con un plugin, así que en ocasiones es necesario acudir a algunos trucos para conseguir tu objetivo.

He tenido que hacer algunas mejoras en la librería Plugin Tools para permitirle hacer algunos de estos trucos, así que la entrada de hoy empieza explicando en qué consisten estas mejoras para verlas luego en acción sobre casos prácticos.


Añadiendo más funciones de HTTP en PluginTools

Los ejemplos que hemos visto hasta ahora han utilizado la función “read” de PluginTools de una forma muy sencilla: le pasas la URL que quieres leer y te devuelve una cadena con el contenido de esa URL.

body = plugintools.read("http://www.mimediacenter.info")

Cuando esto no funcione habrá que recurrir a la nueva función “read_body_and_headers” de PluginTools, como una versión mejorada de la función “read” que permitirá un montón de posibilidades nuevas:

body,response_headers = plugintools.read_body_and_headers("http://www.mimediacenter.info", headers=request_headers, post=custom_post, follow_redirects=True, timeout=10)

Entre las que se incluyen:

  • Gestión de cookies transparente
  • Cabeceras personalizadas (parámetro “headers”)
  • Aumentar el tiempo de espera ante conexiones lentas (parámetro “timeout”)
  • Tratamiento automático de páginas comprimidas con Gzip
  • Envios POST (parámetro “post”)
  • Procesar las redirecciones manualmente (parámetro “follow_redirects”)
  • Acceder a las cabeceras de respuesta
  • Información de depuración adicional

El diseño de la función puede que no sea muy elegante, pero lo que perseguía era tener una función compacta, rápida y sencilla. Si quieres una librería para hacer esto de una forma más “pythonica” puedes recurrir a la librería Python Requests, o a la popular Mechanize. Ambas muy utilizadas y recomendables.

Ahora vamos con algunos ejemplos de uso de “read_body_and_headers”.

Que hacer si el sitio web verifica el User-Agent

Empecemos con un caso sencillo. Cuando haces una llamada HTTP utilizando un navegador cualquiera, dentro de la llamada se envía una cabecera especial llamada “User-Agent” que identifica el navegador que está haciendo la llamada.

Este es el ejemplo de lo que se envía en una llamada HTTP hecha con Firefox para leer la página principal de este blog:

GET / HTTP/1.1
Host: www.mimediacenter.info
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive

Puedes observar que una de las líneas empieza por “User-Agent” e identifica al navegador exacto con el que has hecho la petición:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:20.0) Gecko/20100101 Firefox/20.0

Sin embargo cuando haces una llamada HTTP desde Python usando la función “read” de PluginTools, el navegador empleado es el módulo estándar urllib2 de Python. Y el User-Agent que se manda así lo indica:

GET / HTTP/1.1
User-Agent: Python-urllib/2.1
Host: www.mimediacenter.info
Accept: */*

Puedes ver que en este caso la llamada tiene menos cabeceras, y que el User-Agent identifica claramente a Python como originador de la misma:

Python-urllib/2.1

El caso es que hay sitios web que detectan el User-Agent y lo utilizan con diversos fines, como mostrar un sitio web adaptado al navegador desde el que accedes (útil para móviles) o incluso para bloquear el acceso a ciertos dispositivos.

Por suerte HTTP es un protocolo abierto y bien documentado, de hecho su especificación es una lectura muy recomendable si te dedicas a esto. Con la suficiente habilidad es fácil engañar a cualquier servidor web, y en este caso no podría ser más sencillo ya que basta con enviar la cabecera User-Agent que queramos para que el sitio web no sea capaz de identificarnos como un plugin.

Esto del User-Agent es tan importante que por defecto la función “read_body_and_headers” de PluginTools utiliza un User-Agent de ordenador, concretamente Firefox 18.0 para Mac, siempre que la usas. Si quieres indicar cualquier otro User-Agent basta con que añadas una cabecera HTTP con el parámetro “headers”.

body,response_headers = plugintools.read_body_and_headers("http://www.mimediacenter.info", headers=[["User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31"]])

Verás que “headers” es una lista de cabeceras, que contiene a su vez dos elementos para el nombre de la cabecera y el valor. En el ejemplo la petición se lanza identificándose como “Google Chrome” para Mac.

GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31
Host: www.mimediacenter.info
Accept: */*

Una forma de hacer lo mismo pero más legible, especialmente cuando necesitas añadir varias cabeceras, es añadirlas una por una al array en lugar de declararlo todo en la misma línea:

request_headers=[]
request_headers.append(["User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31"])
body,response_headers = plugintools.read_body_and_headers("http://www.mimediacenter.info", headers=request_headers)

Cuestión de gustos, pero la legibilidad del código es importante 🙂

Qué hacer si el sitio web verifica el Referer

Si User-Agent es la cabecera que se envía para que el sitio web sepa qué programa estás utilizando, Referer es la cabecera que se envía para informarle de la página desde donde vienes.

Esta información se utiliza en los sitios web para seguir la navegación del usuario (saber el camino que sigue en un sitio web), y también se utiliza en muchos casos como medida de protección contra el hot-linking.

Te la encontrarás por ejemplo si quieres datos de una página que se encuentran dentro de un iframe, o cuando quieras realizar una llamada AJAX para resolver la paginación. Son casos bastante habituales, y los detectarás cuando pidas una página y el sitio web te devuelva otra, o un error.

La solución es tan sencilla como añadir una segunda cabecera a nuestro ejemplo, poniendo una nueva cabecera “Referer” en la lista para indicar la página de origen que el sitio web esté esperando.

Supongamos que para acceder a la página principal de Plugin Tools en Mi Media Center (http://www.mimediacenter.info/plugintools) fuera necesario hacerlo desde la página principal del sitio (http://www.mimediacenter.info). Bastará con indicar la URL de la página principal como “Referer” al hacer la petición.

request_headers=[]
request_headers.append(["User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31"])
request_headers.append(["Referer","http://www.mimediacenter.info/"])
body,response_headers = plugintools.read_body_and_headers("http://www.mimediacenter.info/plugintools/", headers=request_headers)

Puedes ver ejemplos de sitios web que utilizan la verificación del Referer en el código fuente de pelisalacarta, por ejemplo AnimeID, Beeg, Cuevana, JKAnime, Tucinecom, …

Próxima entrada

Todavía quedan algunos trucos más que contar, pero esta entrada ya se está haciendo demasiado larga. En la próxima entrada veremos algunos más incluyendo cómo resolver el caso de un sitio web que requiere login.

Descarga ya la nueva versión de Plugin Tools y anímate a hacer tus propios proyectos, es fácil 🙂

]]>
http://www.mimediacenter.info/2013/04/28/como-programar-add-ons-en-xbmc-leyendo-datos-de-fuentes-complicadas/feed/ 3
Aprovecha la capacidad del formato MKV para organizar tu colección de vídeos http://www.mimediacenter.info/2013/01/20/aprovecha-la-capacidad-del-formato-mkv-para-organizar-tu-coleccion-de-videos/ http://www.mimediacenter.info/2013/01/20/aprovecha-la-capacidad-del-formato-mkv-para-organizar-tu-coleccion-de-videos/#comments Sat, 19 Jan 2013 23:26:01 +0000 http://www.mimediacenter.info/?p=1198 Aprovechando unos días tranquilos hace poco me decidí por fin a organizar mi colección de pelis. En primer lugar porque ocupan un espacio considerable en disco y hace tiempo que había detectado formas de mejorarlo y tener más espacio libre, pero también para tenerlas mejor clasificadas.

Entre otras cosas pensé en aprovechar la capacidad del formato MKV a la hora de gestionar vídeos complejos, para almacenar las películas con sus subtítulos (que tengo en ficheros separados en muchos casos), eliminar las cadenas de audio en otros idiomas, unir las películas que están partidas en varios ficheros, y cosas por el estilo.

Tengo unas notas dispersas sobre los comandos que se deben utilizar para cada caso, y he pensado que podría ser interesante recopilarlos todos en esta entrada.

Hay una estupenda herramienta visual para hacerlo casi todo, llamada mkvmerge GUI, pero encuentro una pesadez usarla para procesar muchos vídeos. La línea de comandos es mucho más ágil para esto, y te permite hacer scripts para procesar los vídeos en bloque.

Cómo unir todas las partes de un vídeo en un único fichero MKV (sin recomprimir)

Algo bastante habitual es tener una peli grabada en varios ficheros, muchas veces a causa de la práctica que había antes de separar las pelis largas en ficheros del tamaño de un CD (700MB).

Sorprendentemente el formato MKV permite tener los dos fragmentos de vídeo en el mismo fichero, y los reproduce uno detrás de otro sin saltos como si nunca hubieran estado separados.

Para conseguir esto debes usar el comando “mkvmerge” y unir todas las partes con la siguiente sintaxis, donde “salida.mkv” es el archivo que vas a conseguir al final y “parte1.avi”, “parte2.avi” y “parte3.avi” son cada uno de los fragmentos:

mkvmerge -o salida.mkv parte1.avi +parte2.avi +parte3.avi ...

Ten cuidado de que cada símbolo “+” tenga un espacio antes, y de que no lo tenga después. Es importante.

Veamos un ejemplo, donde tengo la película de “Tron” en dos ficheros “Tron (CD1).avi” y “Tron (CD2).avi”.

jesus@mediaserver:~$ mkvmerge -o Tron.mkv Tron\ \(CD1\).avi +Tron\ \(CD2\).avi 
mkvmerge v5.1.0 ('And so it goes') creado el Feb  1 2012 11:31:23
'Tron (CD1).avi': Using the demultiplexer for the format 'AVI'.
'Tron (CD2).avi': Using the demultiplexer for the format 'AVI'.
'Tron (CD1).avi' pista 0: Using the output module for the format 'MPEG-4'.
'Tron (CD1).avi' pista 1: Using the output module for the format 'MP3'.
'Tron (CD2).avi' pista 0: Using the output module for the format 'MPEG-4'.
'Tron (CD2).avi' pista 1: Using the output module for the format 'MP3'.
El archivo Tron.mkv ha sido abierto para su escritura.
Uniendo la pista 1 del archivo n.º 1 ('Tron (CD2).avi') a la pista 1 del archivo n.º 0 ('Tron (CD1).avi').
Uniendo la pista 0 del archivo n.º 1 ('Tron (CD2).avi') a la pista 0 del archivo n.º 0 ('Tron (CD1).avi').
Progreso: 100%
El índice está siendo escrito...
Muxing took 1 minuto 14 segundos.

Al final del proceso conviene abrir el resultado con un reproductor. Comprueba que la duración es coherente y salta por varios puntos de la película para verificar que se vea bien y el audio está sincronizado, ya que si el fichero de entrada está corrupto podrías tener un vídeo incompleto en la salida.

Cómo convertir un fichero AVI a uno MKV (sin recomprimir)

En realidad el formato .AVI no es el mejor del mundo, pero si tienes un vídeo en .AVI que te hayas descargado de Internet tampoco es necesario que lo conviertas de formato. Y convertirlo a MKV no va a hacer que tenga más calidad, eso es un mito 🙂

Sin embargo si eres de los que te gusta tener todo ordenadito y con la misma extensión, debes saber que puedes convertir el formato de cualquier vídeo a .MKV sin recomprimirlo (y por tanto sin pérdida de calidad alguna) usando el comando mkvmerge.

mkvmerge -o salida.mkv entrada.avi

Y un ejemplo:

jesus@mediaserver:~$ mkvmerge -o Tron.mkv Tron.avi
mkvmerge v5.1.0 ('And so it goes') creado el Feb  1 2012 11:31:23
'Tron.avi': Using the demultiplexer for the format 'AVI'.
'Tron.avi' pista 0: Using the output module for the format 'MPEG-4'.
'Tron.avi' pista 1: Using the output module for the format 'MP3'.
El archivo Tron.mkv ha sido abierto para su escritura.
Progreso: 100%
El índice está siendo escrito...
Muxing took 2 minutos 5 segundos.
jesus@mediaserver:~$ 

Cómo quitar cadenas de audio en otros idiomas

A mí me gusta ver cine en versión original (depende de la peli) pero a la hora de guardarlas para mi colección no me gusta hacerlo más que con el audio en español. Puedes grabar una peli con varias cadenas de audio y subtítulos, por supuesto, pero el audio es algo que ocupa espacio y especialmente si está codificado con AC3.

La forma de extraer las cadenas de audio que no quieres es volver a grabar el vídeo en un nuevo fichero, pero copiando sólo las cadenas de audio que te interesan. Lo primero es identificar la cadena de audio “buena” con el comando:

mkvmerge -i entrada.mkv

Para a continuación crear un nuevo fichero indicando el número de la cadena de audio “buena”:

mkvmerge -o salida.mkv --atracks NUMERO entrada.mkv

O los “números” si quieres conservar más de de una cadena de audio:

mkvmerge -o salida.mkv --atracks NUMERO,NUMERO entrada.mkv

Veamos un ejemplo con la peli de “Wanted” que tengo en mi disco.

jesus@mediaserver:/media/CINE$ mkvmerge -i Wanted\ \(2008\)\ \[720p\].mkv 
Archivo 'Wanted (2008) [720p].mkv': contenedor: Matroska
La ID de la pista 1: video (V_MPEG4/ISO/AVC)
La ID de la pista 2: audio (A_AC3)
La ID de la pista 3: audio (A_AC3)
La ID de la pista 4: subtitles (S_TEXT/UTF8)
jesus@mediaserver:/media/CINE$ 

Como ves, tiene dos pistas de audio y una de subtítulos. Lo normal es que la primera cadena de audio sea en español y la siguiente en inglés, pero puedes asegurarte usando el comando “mkvinfo”.

jesus@mediaserver:/media/CINE$ mkvinfo Wanted\ \(2008\)\ \[720p\].mkv
...
| + Una pista
|  + Número de pista: 2
...
|  + Idioma: spa
|  + Nombre: Castellano AC3 5.1

De forma que el audio en español es la cadena 2. Ahora vamos con mkvmerge:

jesus@mediaserver:/media/CINE$ mkvmerge -o salida/Wanted\ \(2008\)\ \[720p\].mkv --atracks 2 Wanted\ \(2008\)\ \[720p\].mkv 
mkvmerge v5.1.0 ('And so it goes') creado el Feb  1 2012 11:31:23
'Wanted (2008) [720p].mkv': Using the demultiplexer for the format 'Matroska'.
'Wanted (2008) [720p].mkv' pista 1: Using the output module for the format 'AVC/h.264'.
'Wanted (2008) [720p].mkv' pista 2: Using the output module for the format 'AC3'.
'Wanted (2008) [720p].mkv' pista 4: Using the output module for the format 'text subtitles'.
El archivo salida/Wanted (2008) [720p].mkv ha sido abierto para su escritura.
Progreso: 100%
El índice está siendo escrito...
Muxing took 1 minuto 8 segundos.
jesus@mediaserver:/media/CINE$

El resultado es un fichero que pasa de 2,6GB a 2,2GB.

-rwxrwxrwx 1 jesus jesus 2,6G jul 13  2010 Wanted (2008) [720p].mkv
-rw-rw-r-- 1 jesus jesus 2,2G ene 19 19:24 salida/Wanted (2008) [720p].mkv

Para ser exactos el tamaño se redujo en 354MB. No está mal para 1 minuto de procesamiento, si haces esto con 100 pelis tendrás 35GB libres más en tu disco. Y yo tengo más de 100 🙂

Cómo añadir audio en otros idiomas

Si lo que quieres hacer es la operación contraria es más sencillo todavía. Y es realmente sencillo porque es para lo que se diseñó la herramienta mkvmerge: para construir archivos MKV a partir de diferentes elementos.

mkvmerge -o salida.mkv video.mp4 audio.aac

Observa que este caso es muy similar al que usábamos para concatenar dos vídeos, pero no utilizamos el símbolo “+”.

Cómo añadir subtítulos desde un fichero externo

Algo muy habitual es descargarte la peli por un lado, y los subtítulos por otro. En mi caso ocurre a menudo con los documentales de la BBC que descargo de mvgroup.org, y acabo teniendo un montón de ficheritos al lado de cada vídeo.

El comando para hacer esto con mkvmerge es el mismo que en el caso anterior, ya que la cadena de subtítulos no es más que una pista adicional para añadir al vídeo.

mkvmerge -o salida.mkv video.mp4 subtitulo.srt

Aunque si el subtítulo es UTF-8 debes tener en cuenta algún parámetro más:

mkvmerge -o salida.mkv video.mp4 --sub-charset 0:UTF8 -s 0 -D -A subtitulo.srt

Veamos un ejemplo, de estos tengo bastantes, de una peli con dos cadenas de audio.

jesus@mediaserver:/media/CINE$ mkvmerge -i Toy\ Story\ 3\ \[HDrip\]-original.mkv 
Archivo 'Toy Story 3 [HDrip]-original.mkv': contenedor: Matroska
La ID de la pista 1: video (V_MS/VFW/FOURCC, XVID)
La ID de la pista 2: audio (A_AC3)
La ID de la pista 3: audio (A_AC3)

Añadimos dos archivos de subtítulos:

jesus@mediaserver:/media/CINE$ mkvmerge -o Toy\ Story\ 3\ \[HDrip\].mkv Toy\ Story\ 3\ \[HDrip\]-final.mkv Toy\ Story\ 3\ \[HDrip\]\ es.srt Toy\ Story\ 3\ \[HDrip\]\ inglés.srt 
mkvmerge v5.1.0 ('And so it goes') creado el Feb  1 2012 11:31:23
'Toy Story 3 [HDrip]-final.mkv': Using the demultiplexer for the format 'Matroska'.
'Toy Story 3 [HDrip] es.srt': Using the demultiplexer for the format 'SRT subtitles'.
'Toy Story 3 [HDrip] inglés.srt': Using the demultiplexer for the format 'SRT subtitles'.
'Toy Story 3 [HDrip]-final.mkv' pista 1: Using the output module for the format 'MPEG-4'.
'Toy Story 3 [HDrip]-final.mkv' pista 2: Using the output module for the format 'AC3'.
'Toy Story 3 [HDrip]-final.mkv' pista 3: Using the output module for the format 'AC3'.
'Toy Story 3 [HDrip] es.srt' pista 0: Using the output module for the format 'text subtitles'.
'Toy Story 3 [HDrip] inglés.srt' pista 0: Using the output module for the format 'text subtitles'.
El archivo Toy Story 3 [HDrip].mkv ha sido abierto para su escritura.
Progreso: 100%
El índice está siendo escrito...
Muxing took 58 segundos.

Para acabar teniendo un archivo con 2 pistas de audio y dos subtítulos:

jesus@mediaserver:/media/CINE$ mkvmerge -i Toy\ Story\ 3\ \[HDrip\].mkv 
Archivo 'Toy Story 3 [HDrip].mkv': contenedor: Matroska
La ID de la pista 1: video (V_MS/VFW/FOURCC, XVID)
La ID de la pista 2: audio (A_AC3)
La ID de la pista 3: audio (A_AC3)
La ID de la pista 4: subtitles (S_TEXT/UTF8)
La ID de la pista 5: subtitles (S_TEXT/UTF8)
]]>
http://www.mimediacenter.info/2013/01/20/aprovecha-la-capacidad-del-formato-mkv-para-organizar-tu-coleccion-de-videos/feed/ 1
Cómo programar add-ons en XBMC / Kodi: Un add-on más completo (continuación) http://www.mimediacenter.info/2013/01/13/como-programar-add-ons-en-xbmc-un-add-on-mas-completo-continuacion/ http://www.mimediacenter.info/2013/01/13/como-programar-add-ons-en-xbmc-un-add-on-mas-completo-continuacion/#comments Sat, 12 Jan 2013 23:37:55 +0000 http://www.mimediacenter.info/?p=1241 Ayer vimos cómo añadir la sección de vídeos de la web oficial de Disney Junior, analizando paso a paso la extracción de los vídeos del listado, cómo añadirlos a la lista de items de XBMC, y cómo reproducir un vídeo seleccionado por el usuario.

Hoy terminamos el add-on añadiendo otra sección para ver los vídeos del canal de YouTube de Disney Junior, muy útil porque tiene una playlist para cada una de las series incluyendo algunos extras como el karaoke “Canta con Disney Junior”.

También veremos cómo utilizar el teclado en pantalla de XBMC para incluir un buscador, que nos permita acceder fácilmente a una lista de resultados relevantes en YouTube, y cómo utilizar el sistema de configuración de un add-on en XBMC para dejar que el usuario personalice algunos aspectos.

¿Comenzamos?


Las series del canal de YouTube

Si recuerdas el add-on con el que empezó esta serie de tutoriales, uno sencillito que permitía acceder a los vídeos de mi propio canal de YouTube, verás que hacer lo mismo con cualquier otro canal de YouTube no es más complicado que cambiar el ID del canal en el código.

Sin embargo ese add-on utilizaba el API de YouTube para obtener la lista de vídeos subidos al canal

http://gdata.youtube.com/feeds/api/users/tvalacarta/uploads

pero para el de Disney Junior lo que nos interesa es tener la lista de las “playlists” que el propietario del canal ha definido.

http://gdata.youtube.com/feeds/api/users/DisneyJuniorES/playlists

De esta forma al seleccionar la opción “Canal de YouTube” obtendremos una lista de las series de Disney Junior, y al seleccionarlas podremos obtener una lista de vídeos de esa serie. Cada niño tiene sus preferencias.

Aunque podríamos parsear el XML que nos devuelve YouTube usando las librerías de XML de Python, probablemente de una forma más elegante, lo normal en un add-on va a ser encontrarse HTML así que vamos a usar expresiones regulares. Además quedará más compacto, créeme.

Como la estructura de un feed RSS es una sucesión de tags <entry> para cada vídeo, con la información del vídeo dentro de esos tags, vamos a utilizar una forma un poco distinta de extraer los datos.

En primer lugar vamos a utilizar una expresión regular sencilla que nos va a devolver un array con el texto que hay dentro de cada uno de los bloques <entry>.

119 # Show all YouTube playlists for the selected channel
120 def youtube_playlists(params):
121     plugintools.log("disneyjunior.youtube_playlists "+repr(params))
122
123     # Fetch video list from YouTube feed
124     data = plugintools.read( params.get("url") )
125     plugintools.log("data="+data)
126    
127     # Extract items from feed
128     pattern = ""
129     matches = plugintools.find_multiple_matches(data,"<entry(.*?)</entry>")

Y ahora vamos a recorrer ese array extrayendo los datos de los vídeos para añadirlos a la lista de items de XBMC. Como dentro de un tag <entry> sólo hay un vídeo, usaremos la función find_single_match de Plugin Tools para sacar los valores.

    
131     for entry in matches:
132         plugintools.log("entry="+entry)

El título está entre los tags <title>, pero utilizaremos una curiosa expresión regular en este caso.

    
135         title = plugintools.find_single_match(entry,"<titl[^>]+>([^<]+)</title>")

Si utilizo como expresión regular

<title>([^<]+)</title>

El patrón fallará cuando se encuentre con cosas como esta:

"<title >Ejemplo</title>
"<title lang="es">Ejemplo</title>
...

Así que sustituyo <title> por <titl[^>]+> de forma que cuando el patrón haya encontrado las primeras letras del nombre del tag “titl”, deje de buscar para ir directamente al cierre de tag “>”. Esto nos lo habríamos evitado usando un parser XML tradicional, pero el truco es útil también en HTML 🙂

El resto de elementos del feed se extraen de forma similar. El argumento del vídeo está en el tag <media:description>, la imagen en el tag <media:thumbnail> y la URL de la lista de vídeos en el tag <content> que tiene como atributo type “application/atom+xml;type=feed”.

Observa que hay un caracter “\” antes de los símbolos “=”, “+” y “;” debido a que tienen un significado especial dentro de una expresión regular, pero en este caso nos interesa su valor literal. Queremos la cadena “atom+xml”, y no la interpretación de “uno o más” que tiene el símbolo “+”.

    
136         plot = plugintools.find_single_match(entry,"<media\:descriptio[^>]+>([^<]+)</media\:description>")
137         thumbnail = plugintools.find_single_match(entry,"<media\:thumbnail url='([^']+)'")
138         url = plugintools.find_single_match(entry,"<content type\='application/atom\+xml\;type\=feed' src='([^']+)'/>")
139 
140         # Appends a new item to the xbmc item list
141         plugintools.add_item( action="youtube_videos" , title=title , plot=plot , url=url , thumbnail=thumbnail , folder=True )

Al añadir cada elemento a la lista de items de XBMC indicamos la acción “youtube_videos”, que mostrará la lista de vídeos incluidos en la playlist de la URL.

Con esto ya tenemos la lista de playlists del canal, no tenemos que preocuparnos de la paginación como en el plugin de “Mi media center” ya que la llamada de YouTube no permite paginación y siempre devuelve la lista completa.

Los vídeos de cada serie

Como la URL de la lista de vídeos está en el parámetro “url”, y lo que estamos procesando es nuevamente un feed XML, la función “youtube_videos” acaba siendo muy similar a la anterior así que no vamos a verla en detalle.

Observa únicamente que en este caso la URL que añadimos tiene el esquema “plugin://plugin.video.youtube/”, ya que estamos componiéndola de forma que al seleccionar el vídeo se llame al add-on de YouTube para su reproducción. Y como el elemento que añadimos en este paso es directamente reproducible, lo marcamos como “folder=False” para que XBMC sepa que no tiene que descender más.

144 # Show all YouTube videos for the selected playlist
145 def youtube_videos(params):
146     plugintools.log("disneyjunior.youtube_videos "+repr(params))
147
148     # Fetch video list from YouTube feed
149     data = plugintools.read( params.get("url") )
150     plugintools.log("data="+data)
151    
152     # Extract items from feed
153     pattern = ""
154     matches = plugintools.find_multiple_matches(data,"<entry(.*?)</entry>")
155     
156     for entry in matches:
157         plugintools.log("entry="+entry)
158         
159         # Not the better way to parse XML, but clean and easy
160         title = plugintools.find_single_match(entry,"<titl[^>]+>([^<]+)</title>")
161         title = title.replace("Disney Junior España | ","")
162         plot = plugintools.find_single_match(entry,"<summa[^>]+>([^<]+)</summa")
163         thumbnail = plugintools.find_single_match(entry,"<media\:thumbnail url='([^']+)'")
164         video_id = plugintools.find_single_match(entry,"http\://www.youtube.com/watch\?v\=([0-9A-Za-z_-]{11})")
165         url = "plugin://plugin.video.youtube/?path=/root/video&action=play_video&videoid="+video_id
166
167         # Appends a new item to the xbmc item list
168         plugintools.add_item( action="play" , title=title , plot=plot , url=url , thumbnail=thumbnail , isPlayable=True, folder=False )

Cuando el usuario selecciona un vídeo se llama a la función “play”.

Reproducción del vídeo

La función “play” es muy sencilla, a diferencia del caso de “disneyweb_play” que veíamos ayer, ya que la URL que viene como parámetro es directamente algo que XBMC sabe reproducir.

169 # Play selected vieo
170 def play(params):
171     plugintools.play_resolved_url( params.get("url") )

Una simple llamada a play_resolved_url de Plugin Tools le indica a XBMC que puede empezar la reproducción.

Configuración

Antes de ver el buscador es necesario conocer primero cómo funciona el mecanismo que XBMC pone a disposición de los add-ons para gestionar los parámetros de configuración. Esto es así porque el buscador hace uso de algunos de estos parámetros.

Para que tu add-on tenga configuración tienes que crear un fichero “settings.xml” dentro del directorio “resources”, donde especificar uno por uno los parámetros que vas a emplear.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
    <setting id="youtube_channel_id" type="text" option="writeable" label="30006" default="DisneyJuniorES"/>
    <setting id="youtube_language" type="text" option="writeable" label="30007" default="es"/>
    <setting id="last_search" type="text" option="writeable" label="30001" default="la casa de mickey mouse"/>
</settings>

En este caso he definido 3 parámetros

  • youtube_channel_id: Indica el ID del canal de YouTube que se mostrará cuando el usuario seleccione esta opción, con un valor por defecto de “DisneyJuniorES” que es la versión española. Puedes poner “DisneyJuniorLA”, “DisneyJuniorUK”, … o cualquier otro 🙂
  • youtube_language: Indica el idioma de los resultados de búsqueda, por defecto “es” para que salgan vídeos en español pero puedes poner cualquier código de idioma ISO.
  • last_search: Es la última búsqueda que has introducido, para que la siguiente vez que uses el buscador la recuerde y te la proponga

Observa que los parámetros tienen un atributo “type” que te permite indicar “text”, como en este caso, pero hay otros muchos tipos como “number”, “folder”, … La lista completa está en la Wiki de XBMC.

El texto que se muestra al usuario está en el atributo “label”, donde puedes poner directamente una cadena de texto o como en mi caso el ID de la cadena en el fichero strings.xml. Así el diálogo de configuración estará también traducido al idioma del usuario.

Con este fichero presente tu add-on ya es configurable, y si en la lista de add-ons instalados seleccionas la opción “Configuración del Add-on” con el menú contextual podrás acceder al diálogo de configuración.

Como esto es algo complejo para el usuario yo prefiero poner una opción dentro del add-on para abrir el cuadro de diálogo, en este caso una que llama a la función “preferences” que a su vez encarga de abrir este cuadro de diálogo.

Y lo hace con la función open_settings_dialog de Plugin Tools.

173 # Open preferences dialog
174 def preferences(params):
175     plugintools.log("disneyjunior.preferences "+repr(params))
176
177     plugintools.open_settings_dialog()

En el siguiente punto veremos cómo se implementa el buscador, y de paso cómo leer y escribir los valores de los parámetros de configuración desde el código de tu add-on.

Buscador

La función que XBMC ejecuta cuando seleccionas el buscador es muy sencilla, lo único que hace es leer el valor de “last_search” en la configuración para ver la última búsqueda que escribiste. Para ello utiliza la función get_setting.

Luego abre el teclado usando la función keyboard_input, almacena el resultado de nuevo en “last_search” usando la función set_setting.

179 # Open a popup dialog for input search terms, then call the result function
180 def search(params):
181     plugintools.log("disneyjunior.search "+repr(params))
182
183     last_search = plugintools.get_setting("last_search")
184     texto = plugintools.keyboard_input(last_search)
185     plugintools.set_setting("last_search",texto)
186
187     params["texto"]=texto
188    
189     youtube_search(params)

Una vez que tiene el texto tecleado lo almacena como un parámetro “texto” y llama a la función “youtube_search”, que es similar a las anteriores ya que procesa un feed XML de YouTube con los resultados.

La única diferencia es que la llamada al API de YouTube es diferente. Usa el servicio “videos” de YouTube indicando en el parámetro “q” el texto que el usuario ha tecleado, y en el parámetro “lr” el idioma que ha puesto en la configuración.

191 # Show first 50 videos from YouTube that matches a search string
192 def youtube_search(params):
193     plugintools.log("disneyjunior.search "+repr(params))
194
195     # Fetch video list from YouTube feed
196     data = plugintools.read( "https://gdata.youtube.com/feeds/api/videos?q="+params.get("texto").replace(" ","+")+"&orderby=published&start-index=1&max-results=50&v=2&lr="+plugintools.get_setting("youtube_language") )
197     plugintools.log("data="+data)
198    
199     # Extract items from feed
200     pattern = ""
201     matches = plugintools.find_multiple_matches(data,"<entry(.*?)</entry>")
202    
203     for entry in matches:
204         plugintools.log("entry="+entry)
205        
206         # Not the better way to parse XML, but clean and easy
207         title = plugintools.find_single_match(entry,"<titl[^>]+>([^<]+)</title>")
208         plot = plugintools.find_single_match(entry,"<summa[^>]+>([^<]+)</summa")
209         thumbnail = plugintools.find_single_match(entry,"<media\:thumbnail url='([^']+)'")
210         video_id = plugintools.find_single_match(entry,"http\://www.youtube.com/watch\?v\=([0-9A-Za-z_-]{11})")
211         if video_id=="":
212             video_id = plugintools.find_single_match(entry,"https\://www.youtube.com/watch\?v\=([0-9A-Za-z_-]{11})")
213         url = "plugin://plugin.video.youtube/?path=/root/video&action=play_video&videoid="+video_id
214
215         # Appends a new item to the xbmc item list
216         plugintools.add_item( action="play" , title=title , plot=plot , url=url , thumbnail=thumbnail , isPlayable=True, folder=False )

El resultado son los primeros 50 elementos que coinciden con el texto buscado, en el idioma elegido por el usuario. Y la acción de cada vídeo individual es la misma función “play” que en el caso anterior.

Mensajes al usuario

No he utilizado en este caso mensajes para el usuario, pero la librería Plugin Tools incluye una función message que te permite mostrar una alerta en caso necesario.

plugintools.message("Disney Junior","Ejemplo de mensaje")

Descarga el add-on de Disney Junior

Aunque estaba en la entrada de ayer, incluyo de nuevo el enlace al add-on completo para que puedas descargarlo y estudiarlo cómodamente. Es totalmente funcional, también puedes usarlo para ver algún vídeo si quieres 🙂

http://www.mimediacenter.info/descargas/plugin.video.disneyjunior-1.0.0.zip

Próxima entrega

Ya queda poco para llegar al final de esta serie de tutoriales sobre cómo programar add-ons para XBMC, espero que te estén gustando y que te animen a desarrollar tus propios add-ons 🙂

En la próxima entrega veremos algunas técnicas para leer datos de sitios web que no son tan sencillos, como sitios que requieran usuario y contraseña o que requieran cookies. Aprovecharé para ampliar la funcionalidad de Plugin Tools de nuevo para hacer que resulte sencillo.

]]>
http://www.mimediacenter.info/2013/01/13/como-programar-add-ons-en-xbmc-un-add-on-mas-completo-continuacion/feed/ 15
Cómo programar add-ons en XBMC / Kodi: Un add-on más completo http://www.mimediacenter.info/2013/01/12/como-programar-add-ons-en-xbmc-un-add-on-mas-completo/ http://www.mimediacenter.info/2013/01/12/como-programar-add-ons-en-xbmc-un-add-on-mas-completo/#comments Fri, 11 Jan 2013 23:48:47 +0000 http://www.mimediacenter.info/?p=1161 Estamos a mitad de camino de este tutorial, pero ya tienes el conocimiento necesario para hacer un add-on bastante completo. Espero que a estas alturas ya te hayas convencido de que es algo relativamente sencillo sin necesidad de saber demasiado de programación. Y ya sabes cómo obtener datos de una página HTML usando expresiones regulares, que es lo más difícil.

Así que antes de entrar en la recta final vamos construir un add-on paso a paso desde cero, con el objetivo de afianzar lo que has aprendido en las entregas anteriores y de paso divertirte un poco.

Te aconsejo que elijas un sitio web que te guste como fuente de vídeos, para mí he elegido hacer un add-on completo que permita ver los vídeos de Disney Junior tanto en la web oficial como en YouTube. No se trata de un add-on demasiado complejo, como podrás comprobar enseguida, pero no va a desmerecer en nada a cualquiera de los que puedes encontrar publicados en muchos repositorios 🙂

Puedes elegir tu propia fuente para hacer el add-on, siguiendo los mismos pasos que yo voy a dar, o construir conmigo este interesante proyecto.

Ficheros de identificación

Escribir el fichero addon.xml es el primer paso, así tendrás algo con lo que probar las primeras líneas de código que vayas escribiendo. Aquí va el mío donde verás que he cogido el del ejemplo de “Mi Mediacenter” cambiando el id del add-on (lo he llamado plugin.video.disneyjunior), el nombre (“Disney Junior”) y las descripciones:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.disneyjunior"
    name="Disney Junior"
    version="1.0.0"
    provider-name="tvalacarta">
  <requires>
    <import addon="xbmc.python" version="2.0"/>
    <import addon="plugin.video.youtube" version="3.0.0"/>
  </requires>
  <extension point="xbmc.python.pluginsource" library="default.py">
    <provides>video</provides>
  </extension>
  <extension point="xbmc.addon.metadata">
    <summary lang="en">Disney Junior</summary>
    <description lang="en">Watch online Disney Junior videos (spanish)</description>
    <summary lang="es">Disney Junior</summary>
    <description lang="es">Todos los vídeos de Disney Junior online en Español</description>
    <platform>all</platform>
  </extension>
</addon>

Hacer el logo y el fanart requerirá un poco de práctica al principio, pero basta con que sepas manejar un programa de edición de imágenes donde puedas recortar y cambiar de tamaño. Un logo a 256×256 en PNG, y un fanart a 1280×720 en JPG. Ambos sacados de la web de Disney Junior y con algo de ayuda de Google.

El add-on de Disney Junior para XBMC, con su logo y fanart

Un menú de navegación

Un add-on que tenga algo más que unos pocos vídeos necesita un menú para que el usuario pueda elegir lo que quiere hacer. En mi caso tengo bastante claro el menú que tiene que tener un add-on de Disney Junior, porque conozco los gustos de mi hija pequeña.

Primero una opción “Web oficial” que muestre todos los vídeos de la web oficial de Disney Junior, seguido de otra opción “Canal de YouTube” para acceder a las playlists que la cadena tiene en su canal oficial de YouTube. Luego una entrada para recurrir al buscador, ya que solemos ponerle capítulos de Mickey Mouse buscándolos en YouTube, y por último una opción para configurar el add-on.

Hacer el menú es muy sencillo porque no hay que llamar a ningún sitio, simplemente añadir 4 elementos a la lista de items. En el fichero “default.py” de este add-on está hecho con estas líneas.

44 # Main menu
45 def main_list(params):
46    plugintools.log("disneyjunior.main_list "+repr(params))
47
48    plugintools.add_item( 
49        action="disneyweb", 
50        title=plugintools.get_localized_string(T_OFFICIAL_WEBSITE) ,
51        url="http://www.disney.es/disney-junior/contenido/video.jsp" ,
52        folder=True )
53    
54    plugintools.add_item(
55        action="youtube_playlists",
56        title=plugintools.get_localized_string(T_YOUTUBE_CHANNEL),
57        url="http://gdata.youtube.com/feeds/api/users/"+YOUTUBE_CHANNEL_ID+"/playlists?v=2&start-index=1&max-results=30",
58        folder=True )
59    
60    plugintools.add_item( action="search",
61        title=plugintools.get_localized_string(T_SEARCH) )
62    
63    plugintools.add_item( action="preferences",
64        title=plugintools.get_localized_string(T_PREFERENCES),
65        folder = False )

Observarás que los títulos no están escritos directamente:

title = "Canal de YouTube"

sino que utilizan la función get_localized_string de Plugin Tools y un identificador numérico para la cadena de texto:

title = plugintools.get_localized_string(30003)

o mejor el identificador numérico de la cadena lo ponemos como una constante para mayor legibilidad:

T_YOUTUBE_CHANNEL=30003
title = plugintools.get_localized_string(T_YOUTUBE_CHANNEL)

Esto es así por el sistema que proporciona XBMC para tener un add-on donde los textos están adaptados al idioma de cada usuario. Es un poco lioso, pero simple y potente.

La idea es que a los textos que quieres traducir les asocias un identificador numérico (30003 en el ejemplo), y los escribes en un fichero “strings.xml” dentro del directorio “resources/language/Spanish”, “resources/language/English”, etc. Uno para cada idioma.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<strings>
    <string id="30001">Última búsqueda</string>
    <string id="30002">Web oficial</string>
    <string id="30003">Canal de YouTube</string>
    <string id="30004">Buscador ...</string>
    <string id="30005">Configuración ...</string>
    <string id="30006">ID del canal de YouTube ...</string>
    <string id="30007">Idioma para los resultados del buscador</string>
</strings>

Luego los pones en tu código usando la función get_localized_string a la que le pasas el identificador numérico.

Si el usuario tiene su XBMC en inglés, se leerá el fichero strings.xml del directorio “resources/language/English”. Si lo tiene en español, de “resources/language/Spanish”, etc. Si no pones literales en el idioma del usuario se cogerá por defecto los que estén en inglés, así que no olvides poner al menos ese idioma.

Mostrando los vídeos de la web oficial

Abriendo la zona de vídeos de la web de Disney Junior encontrarás el reproductor, y la lista de vídeos disponibles debajo. A mi hija le encanta porque pones un vídeo, y a partir de ahí los reproduce uno detrás de otro en carrusel.

Si le das en Firefox a “Herramientas / Desarrollador web / Código fuente de la página” accedes al HTML, y si buscas dentro del HTML la cadena del título de uno de los vídeos encontrarás enseguida el bloque de HTML que representa a cada vídeo.

Yo lo que suelo hacer para facilitar el trabajo es copiar el HTML que me interesa en cuanto lo localizo, lo pego en el módulo Python que estoy desarrollando dentro de un bloque de comentario, y lo utilizo como punto de partida para construir la expresión regular.

'''
<div class="promo" style="background-image: url(/cms_res/disney-junior/images/promo_support/promo_holders/video.png);">
    <a href="/disney-junior/contenido/video/canta_con_dj_arcoiris.jsp " class="promoLinkTracking"><img src="/cms_res/disney-junior/images/video/canta_dj_arco_iris_164x104.jpg" class="promo_image" alt=""/></a>
    <div class="promo_title_3row"><p>Canta con DJ: La canción del arco iris</p></div>
    <a class="playlist_button_large"  href="" ref="canta_con_dj_arcoiris"><img src="/cms_res/disney-junior/images/promo_support/playlist_add_icon.png" alt="" /></a>
</div>
'''

A continuación pego el html tal como está dentro de una variable, para ir sustituyendo paso a paso y cometer los menos errores posibles:

pattern ='<div class="promo" style="background-image: url(/cms_res/disney-junior/images/promo_support/promo_holders/video.png);">'
pattern+='<a href="/disney-junior/contenido/video/canta_con_dj_arcoiris.jsp " class="promoLinkTracking"><img src="/cms_res/disney-junior/images/video/canta_dj_arco_iris_164x104.jpg" class="promo_image" alt=""/></a>'
pattern+='<div class="promo_title_3row"><p>Canta con DJ: La canción del arco iris</p></div>'
pattern+='<a class="playlist_button_large"  href="" ref="canta_con_dj_arcoiris"><img src="/cms_res/disney-junior/images/promo_support/playlist_add_icon.png" alt="" /></a>'
pattern+='</div>'

Y entonces empiezo a sustituir. Del primer tag sólo me interesa el principio ya que sirve para marcar el comienzo del patrón, así que dejo un trozo y luego utilizo el patrón [^<]+ para saltar al siguiente tag.

pattern  = '<div class="promo"[^<]+'

El segundo tag del bloque tiene el enlace al vídeo en el atributo href y entre comillas, así que uso el patrón [^”]+ y lo marco entre paréntesis porque me interesa el contenido. Y a continuación salto al siguiente tag con [^<]+:

pattern += '<a href="([^"]+)"[^<]+'

Ahora viene un tag de imagen que necesito para tener la captura del vídeo, aunque esté en la misma línea del texto lo dejo separado para mayor legibilidad.

Cojo la URL de la imagen con el mismo patrón [^”]+ que antes, también entre paréntesis, y salto al siguiente tag con [^<]+:

pattern += '<img src="([^"]+)"[^<]+'

Ya tengo la URL del vídeo y su imagen, sólo necesito el título para poder mostrar la información completa en el add-on. Así que salto los tags que vienen a continuación hasta encontrar el tag <p> que contiene el título. Como es un valor que está entre tags y no en un atributo, utilizo el patrón ([^<]+).

pattern += '</a[^<]+'
pattern += '<div[^<]+'
pattern += '<p>([^<]+)</p>'

Podría haber usado (.*?) para saltar todos los elementos e ir directamente al título, pero intento guardar ese recurso cuando es realmente necesario. De esa forma consigo que la carga de los items sea lo más rápida posible.

Antes de poner el código de este bloque nos falta un detalle. Para evitar que haya algún elemento que coincida con el patrón que acabamos de escribir, pero que no corresponda con un vídeo, voy a limitar la zona de la página donde usaré la expresión regular al bloque donde están los vídeos contenidos.

Observa que todos los vídeos de la página están dentro de una zona que empieza con un <div> concreto, y acaban en una zona delimitada por la siguiente que también empieza con otro <div> concreto.

(aquí están todos los vídeos…)

Para delimitar el área de trabajo de la expresión regular a la zona entre estos dos tags, leo la página con read y la guardo en la variable “data”

data = plugintools.read( params.get("url") )

para inmediatamente después quedarme con la parte donde están los vídeos utilizando el patrón <div id=”video_main_promos_inner”>(.*?)<div id=”content_index_navigation”>. Que viene a ser “todo lo que está entre el primer div y el segundo”.

data = plugintools.find_single_match( data , '<div id="video_main_promos_inner">(.*?)<div id="content_index_navigation">')

Ya tengo todo lo necesario para escribir la función “disneyweb” que extrae los vídeos y los añade a la lista de items de XBMC:

67 # Show all videos from the official website
68 def disneyweb(params):
69     plugintools.log("disneyjunior.disneyweb "+repr(params))
70 
71     # Fetch video list page
72     data = plugintools.read( params.get("url") )
73     data = plugintools.find_single_match( data , '<div id="video_main_promos_inner">(.*?)<div id="content_index_navigation">')
74     
75     # Extract items
76     '''
77     <div class="promo" style="background-image: url(/cms_res/disney-junior/images/promo_support/promo_holders/video.png);">
78         <a href="/disney-junior/contenido/video/canta_con_dj_arcoiris.jsp " class="promoLinkTracking"><img src="/cms_res/disney-junior/images/video/canta_dj_arco_iris_164x104.jpg" class="promo_image" alt=""/></a>
79         <div class="promo_title_3row"><p>Canta con DJ: La canción del arco iris</p></div>
80         <a class="playlist_button_large"  href="" ref="canta_con_dj_arcoiris"><img src="/cms_res/disney-junior/images/promo_support/playlist_add_icon.png" alt="" /></a>
81     </div>
82     '''
83     pattern  = '<div class="promo"[^<]+'
84     pattern += '<a href="([^"]+)"[^<]+'
85     pattern += '<img src="([^"]+)"[^<]+'
86     pattern += '</a[^<]+'
87     pattern += '<div[^<]+'
88     pattern += '<p>([^<]+)</p>'
89     matches = plugintools.find_multiple_matches(data,pattern)

En este punto tengo en la variable “matches” la lista de videos, donde cada elemento de la lista es a su vez una lista con url, imagen y título, sólo falta añadirlos a la lista de items con la función add_item de Plugin Tools.

    
91     for scrapedurl, scrapedthumbnail, scrapedtitle in matches:
92         # Not the better way to parse XML, but clean and easy
93         title = scrapedtitle
94         thumbnail = urlparse.urljoin( params.get("url") , scrapedthumbnail )
95         url = urlparse.urljoin( params.get("url") , scrapedurl.strip() )
96         plot = ""
97 
98         # Appends a new item to the xbmc item list
99         plugintools.add_item( action="disneyweb_play" , title=title , plot=plot , url=url ,thumbnail=thumbnail , isPlayable=True, folder=False )

Observa que la URL y la imagen (o thumbnail) se añaden usando primero la función estándar de Python “urljoin”, lo que viene bien cuando te encuentras con URL relativas en lugar de absolutas. Esta función crea una URL utilizando el primer parámetro como URL base, y el segundo como ruta relativa.

Y observa también que el elemento que añadimos a la lista de items no es una carpeta (folder=False), porque cuando el usuario seleccione uno de estos items simplemente se reproducirá el vídeo con la función “disneyweb_play”. No va a ser necesario que el usuario descienda más niveles, y por eso lo marcamos como “no carpeta”.

Reproducción del vídeo

Cuando el usuario elija un vídeo de la lista anterior, XBMC llamará a la acción “disneyweb_play” y le pasará como parámetro la URL del vídeo elegido entre otras cosas.

Lo primero que hay que hacer es leer esa URL para tener la información del vídeo, usando la función read nuevamente:

101 # Play one video from the official website
102 def disneyweb_play(params):
103     plugintools.log("disneyjunior.disneyweb_play "+repr(params))
104 
105     # Fetch page
106     data = plugintools.read( params.get("url") )

Y ahora utilizar esa información para deducir la URL que hay que darle al reproductor de XBMC. En este caso es fácil porque la URL utiliza el protocolo “RTMPE”, y está en el código HTML separada en dos líneas diferentes de forma bastante clara:

	config.firstVideoSource = 'winnie_heffa_woozles.mp4';
	config.htmlContainerName = 'video_player';
	config.loop = false;
	config.autoplay = true;
	config.rtmpeServer = 'rtmpe://cp121902.edgefcs.net/ondemand/';

Así que sólo tenemos que extraer los dos fragmentos y componerlos para tener la URL completa.

108     url_start = plugintools.find_single_match( data , "config.rtmpeServer \= '([^']+)'")
109     plugintools.log("disneyjunior.disneyweb_play url_start="+url_start)
110 
111     url_end = plugintools.find_single_match( data , "config.firstVideoSource \= '([^']+)'")
112     plugintools.log("disneyjunior.disneyweb_play url_end="+url_end)
113    
114     url = url_start + url_end
115     plugintools.log("disneyjunior.disneyweb_play url="+url)
116 
117     plugintools.play_resolved_url( url )

Con play_resolved_url le decimos a XBMC que está listo para la reproducción, así que directamente empezará a verse el vídeo.

Próxima entrega

La extensión de esta entrada me obliga a dividirla en dos, todavía queda ver cómo montar la sección del canal de YouTube aunque resulta similar a la del ejemplo que vimos al principio de esta serie de tutoriales.

También veremos cómo funciona el buscador y la configuración, pero si has llegado hasta aquí y quieres echarle un vistazo al add-on terminado descargándotelo desde este enlace.

http://www.mimediacenter.info/descargas/plugin.video.disneyjunior-1.0.0.zip

Si no tienes hijos en edad de “La Casa de Mickey Mouse”, pónselo a tus sobrinos. Seguro que sus padres te preguntan cómo pueden instalárselo ellos también 🙂

]]>
http://www.mimediacenter.info/2013/01/12/como-programar-add-ons-en-xbmc-un-add-on-mas-completo/feed/ 19