viernes, 15 de junio de 2012

Generador MP3 para despertador

y pidiéndole peras al olmo

Hoy voy a dejar un poco de lado la domótica, para enseñaros un script muy mono, que llevo usando al rededor de un año. Se trata de agrupar varias disciplinas y servicios web para generar un mp3. Este MP3 es el Máximo de la MáximaFM, que le incrustaremos al principio:

  • el clima actual, con máxima y mínima para hoy
  • las tareas para hoy de Google Calendar
  • las tareas para mañana de Google Calendar
  • los cumpleaños de los contactos de hoy y mañana

Al lio ...

Vamos a usar Google en línea de comandos, algunas webs y nuevos comandos, así que empezamos instalando:
apt-get install googlecl sox ffmpeg mplayer libsox-fmt-mp3
Además nos hace falta el lame. Lo bajamos de Sourceforge y compilamos:
tar -xvzf lame-3.99.5.tar.gz
cd lame-3.99.5
./configure
make
make install
No tiene dificultad, sólo unos minutillos. Ahora configuramos GoogleCL, tenemos que darle permisos para que vea nuestro calendario, de esta forma:
google calendar today
La primera vez nos pide que vayamos a una URL. La abrimos en un navegador y le damos a "conceder acceso", volvemos al RaspberryPi y le damos a intro. Tendremos que ver las tareas de hoy. Veamos otro ejemplo, ver todas las tareas de hoy de todos los calendarios:
google calendar today --cal ".*"
Qué bonito, ahora vamos a ver las tareas de mañana de todos los calendarios:
google calendar list --cal ".*" --date $(date +%Y\-%m\-%d -d "tomorrow")
En mi caso tengo integrado el calendario de los cumpleaños de Facebook, así que me salen los cumpleaños de la gente de Facebook.
Pues teniendo eso, ahora solo queda demostraros una vez más, que mis conocimientos en programación son de lo más burdo, sólo me se 4 ó 5 comanditos con los que lo hago todo. El script se conectará a:
  • nuestros calendarios de tareas y cumpleaños
  • a Google para ver el clima (de Sevilla, pon tu provincia)
  • a la web de Máxima FM para ver el top
  • a Goear para descargar el mp3
  • usará el TTS de Google Translator para generar las frases
  • un poco de magia Debian para trocear los archivos, ajustar volúmenes y esas cosas

Creamos /usr/local/bin/maximafm-temperatura-tareas.sh:
#!/bin/bash
mkdir tmp
cd tmp
wget --header='Accept-Language: es' http://www.google.com/ig/api?weather=sevilla -O clima.xml
cadena=$(cat clima.xml | sed 's/>/>\n/g' | grep condition\ data | head -1 | cut -f2 -d\")
cadena1=$(echo $cadena, temperatura actual $(cat clima.xml | sed 's/>/>\n/g' | grep temp_c\ data | cut -f2 -d\") grados. la mínima para hoy es $(cat clima.xml | sed 's/>/>\n/g' | grep -e low\ data | head -1 | cut -f2 -d\") y la máxima $(cat clima.xml | sed 's/>/>\n/g' | grep -e high\ data | head -1 | cut -f2 -d\"))

wget -F -U "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0" "http://translate.google.com/translate_tts?tl=es&q='$cadena1" -O clima.mp3

wget http://www.maxima.fm/51Chart/ -O salida.txt
inombre=$(cat salida.txt | grep td\ class\=\"izquierda\ verde | head -1 | cut -f3,6 -d\> | sed 's/<\/span//g' | sed 's/>/\ /g' | sed 's/\&//g')/
nombre=$(echo $inombre | sed 's/Rmx//g')
#nombre="Coconut Tree - Mohombi feat. Nicole Scherzinger/"
wget "http://www.goear.com/search/$nombre" -O salida.txt
id=$(cat salida.txt | grep Escuchar | sed 's/v\=/\n/g' | cut -f1 -d\' | grep -v \< | head -1 )
wget -q http://www.goear.com/tracker758.php?f=$id -O salida.xml
wget $(cat salida.xml | cut -f6 -d\") -O original.mp3
mplayer -vc null -vo null -nocorrect-pts -ao pcm:waveheader original.mp3
sox clima.mp3 -r 48000 1.wav rate
sox -c2 -r48000 1.wav 1_2.wav

google calendar today --cal ".*" | grep ^[A-Za-Z] | cut -f1 -d\, > today
google calendar list --cal ".*" --date $(date +%Y\-%m\-%d -d "tomorrow") | grep ^[A-Za-Z] | cut -f1 -d\, > salida

today=$(cat today | grep ^[A-Za-z] | head -1)
tomorrow=$(cat salida | grep ^[A-Za-z] | head -1)
frases=0

if [ -z $today ];
then
        echo "no hay tareas para hoy" > fin.txt
else
        frases=$[$frases+1];
        echo "para hoy tenemos " > fin.txt;
        for n in $(seq 1 $(cat today | grep ^[A-Za-z] | cut -f1 -d\, | sed "s/'s\ Birthday/\ cumpleaños/g" | wc -l));
        do
                echo $(cat today | grep ^[A-Za-z] | cut -f1 -d\, | sed "s/'s\ Birthday/\ cumpleaños/g" | head -$n | tail -1) >> fin.txt;
        done

fi

if [ -z $tomorrow];
then
        echo no hay para mañana;
else
        frases=$[$frases+1];
        echo "para mañana tenemos" >> fin.txt;
        for n in $(seq 1 $(cat salida | grep ^[A-Za-z] | cut -f1 -d\, | sed "s/'s\ Birthday/\ cumpleaños/g" | wc -l));
        do
                echo $(cat salida | grep ^[A-Za-z] | cut -f1 -d\, | sed "s/'s\ Birthday/\ cumpleaños/g" | head -$n | tail -1) >> fin.txt;
        done

fi

for n in $(seq 1 $(cat fin.txt | wc -l));
do
        wget -F -U "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0" "http://translate.google.com/translate_tts?tl=es&q='$(cat fin.txt | head -$n | tail -1)" -O frase$n.mp3
done
for n in $(ls frase*.mp3);
do
        sox $n -r 48000 $(echo $n | sed 's/mp3/wav/g') rate;
done

sox $(echo $(ls frase*.wav)) salida.wav

sox -c2 -r48000 salida.wav salida_2.wav
sox salida_2.wav salida_3.wav speed 0.5
sox -v 2 salida_3.wav salida_1.wav
sox 1_2.wav 1_3.wav speed 0.5
sox -v 2 1_3.wav 1_1.wav
sox audiodump.wav -r 48000 2.wav rate
sox -c2 -r48000 -n -t raw - synth 5.100 sine 18000 vol 0 > base.raw
sox -s2 -c2 -r48000 base.raw silen.wav
sox silen.wav 1_1.wav salida_1.wav fin.wav
duracion1=$(ffmpeg -i salida.wav 2>&1 | grep Duration | cut -f4 -d: | cut -f1 -d.)
for n in $(seq 1 $duracion1); do echo $n > numero; done
duracion=$(cat numero)
sox 2.wav 2_1_1.wav fade t 0 14 8
sox 2_1_1.wav 2_1.wav trim 0 10
sox 2.wav 2_2.wav trim 10 $[$duracion+10]
sox 2.wav 2_3_1.wav trim $[$duracion+10+10-4] 500
sox 2_3_1.wav 2_3_2.wav fade t 8
sox 2_3_2.wav 2_3.wav trim 4 500
sox -v 0.4 2_2.wav 2_4.wav
sox 2_1.wav 2_4.wav 2_3.wav 2.wav
sox -m fin.wav 2.wav total.wav
rm ../despertador.mp3
lame -h -b 192 total.wav /tmp/despertador.mp3
cp original.mp3 ~/mp3/$(echo $nombre | sed 's/\ /_/g' | sed 's/\///g').mp3
cd ..
rm -rf tmp
Tarda en ejecutarse aproximádamente 15 minutos, en un core i5 apenas minuto y medio. Al final final final de todo, eso nos va a crear un archivo que se llama "despertador.mp3" en /usr/local/bin/ y otro con el nombre original en /mnt/mp3 y sin modificar (mapealo en minidlna!).
jummm ... ¿despertador.mp3? ¿Y si ahora creamos una tarea programada para que ejecute el script y otra para que lo reproduzca a las 7:00 am? ¡¡QUÉ BUENÍSIMA IDEA!!

Actualización:
parece ser que la api de Google Weather ha pasado a mejor vida, estoy viendo como hacerlo con Wunderground a ver que tal.

15 comentarios:

  1. Hola! no crea /usr/local/bin/despertador.mp3 ni tampoco /mnt/mp3/despertador.mp3
    No los estas borrando al final del scrip???
    Saludos

    ResponderEliminar
  2. Muy bueno, si señor. Me encanta tu blog, claro, conciso y al grano. Muy interesante, dificil aburrirse, sigue así

    ResponderEliminar
  3. Tengo un error al abrir la web para conseguir el tiempo en XML. Es como si google bloqueara mi equipo al hacer la peticion de http://www.google.com/ig/api?weather=sevillahttp://www.google.com/ig/api?weather=barcelona. Puede ser? Si es asi, se puede solventar de algun modo?

    Esto es lo que me devuelve al hacer wget --header='Accept-Language: es' http://www.google.com/ig/api?weather=sevillahttp://www.google.com/ig/api?weather=barcelona -O clima.xml
    Petición HTTP enviada, esperando respuesta... 403 Forbidden

    ResponderEliminar
    Respuestas
    1. cierto, han cambiado la api o algo por el estilo, vamos a verlo.

      Eliminar
    2. y este es el problema http://thenextweb.com/google/2012/08/28/did-google-just-quietly-kill-private-weather-api/

      Eliminar
  4. No hay problema. He podido cambiar esto cogiendo los datos del tiempo en Yahoo Weather. Información de API aqui http://developer.yahoo.com/weather/

    Aqui lo que hay que sustituir si queremos usar la API de Yahoo:
    El codigo 20078647 corresponde a Rubi, tu cambialo por el codigo de tu ciudad. Mira como encontrar el codigo el la web de la API


    curl --silent "http://xml.weather.yahoo.com/forecastrss?w=20078647&u=c" > weather.tmp
    #Si no hay datos disponibles (p.e. la red ha caido), utilizar los datos anteriormente descargados en lugar de crear un archivo con 0 bytes
    if [ "`ls -l weather.tmp | awk '{print $5}'`" != "0" ]
    then
    mv weather.tmp weather.dat
    fi
    #Creo las cadenas con frases. No pueden ser largas o sino no funcionan debido a la longitud de cabecera.
    saludo="Buenos días Rubén. Despierta que es de día!"
    cadena1=$(echo La temperatura actual en Rubí es de $(grep 'yweather:condition' weather.dat | head -1 | cut -d\" -f6)ºC.)
    cadena2=$(echo La temperatura mínima de hoy es de $(grep 'yweather:forecast' weather.dat | head -1 | cut -d\" -f6)ºC y la máxima de $(grep 'yweather:forecas$
    #Convertimos los textos en mp3 gracias a Google Translator
    wget -F -U "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0" "http://translate.google.com/translate_tts?tl=es&q='$saludo'" -O s$
    wget -F -U "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0" "http://translate.google.com/translate_tts?tl=es&q='$cadena1'" -O $
    wget -F -U "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0" "http://translate.google.com/translate_tts?tl=es&q='$cadena2'" -O $
    #Junto las 3 frases en solo 1 llamada clima.mp3
    sox saludo.mp3 cadena1.mp3 cadena2.mp3 clima.mp3

    ResponderEliminar
  5. Tengo una duda al respecto. He creado una tarea programada para que me genere el MP3 y lo genera perfecto, corrigiendo volumenes y todo.

    Lo que no se como hago otra tarea programada para que reproduzca el MP3 por DLNA a mi Samsung Galaxy S3. Es posible eso? Como seria la linea del crontab?

    ResponderEliminar
    Respuestas
    1. por supuesto que es posible, tienes que dejar el reproductor DLNA en modo escucha en el Samsung y desde el servidor le envias el streaming. Ahora ¿cómo se hace? ni idea :) es de esas cosas que tengo pendiente por aprender ¿como reproducir DLNA por linea de comandos?

      Eliminar
    2. Humm... Eso me hace pensar que, si MiniDLNA es un servidor, quiza deberiamos mirar un reproductor DLNA en linea de comandos. ¿Quiza VLC, Winamp? Estos 2 aceptan linea de comandos. Investigare sobre ello.

      Otra posibilidad que se me ocurrio es subir el MP3 a la carpeta public de Dropbox:
      dropbox_uploader.sh upload /tmp/despertador.mp3 /Public/despertador.mp3

      Mire la direccion publica del enlace del archivo:
      https://dl.dropbox.com/u/1234567/despertador.mp3

      Con el programa que hablastes AutomateIt de Android hago que a la hora de levantarme abra el archivo por internet. PROBLEMA! Si abriera esa direccion en un navegador normal se reproduce el archivo. Si se abre directamente en un navegador android, parece que se va a reproducir, pero no lo hace... Quiza se deberia hacer algun modo que me pase el archivo al movil de algun modo, y en lugar de abrir un navegador reproducir ese archivo,...pero como?

      Alguna otra idea? Tu como lo haces?

      Eliminar
    3. para la parte de copiarlo al movil, instálate un ssh server en el movil (root) y listo. Cuando tengas generado el mp3 lo copias por scp al movil sin mayor problema, sobreescribiendo el archivo en cuestion (root root).
      Lo que me comentas de vlc o winamp ... no lo veo ¿como le digo al vlc del raspberry que me reproduzca un archivo en el movil y por dlna? Seguro que es una chorrada como generar un XML y enviarlo via nc al movil, pero aun no he visto nada de esto.

      Eliminar
    4. Al final me ha dado pereza rootear en Samsung Galaxy S3 solo para eso, asi que he encontrado una aplicacion genial. Folder Sync. con ella puedes sincronizar carpetas de tu Android a Dropbox o Google Drive o varios srvicios en cualquiera de sus sentidos.

      Asi que lo que he hecho es crear el MP3->Subirlo A DropBox->Sincronizar a Android (FolderSync)->Reproducir a una hora determinada el MP3 (AutomateIt).

      Caotico? Quiza si, pero efectivo! :) Ademas del tiempo y las tareas me lee el titular nuevo de este blog por RSS y cuatro cosas mas. IMAGINACION AL PODER!

      Eliminar
    5. A ver, llevo dias con la prueba anterior, y funciona bien. Lo malo, el LAG de tiempo entre que sube a dropbox, y vuelve a sincronizar con foldersync... Ademas con tanta sincronizacion me da que un dia alguna no se hara a tiempo y la hemos fastidiado.

      He conseguido el SSHDROID en Android que tienes acceso por SSH al movil, sin necesidad de rootear el terminal. Entonces la solucion que me dices de hacer una copia con scp al movil, sobreescribiendo el archivo en cuestion (root root).

      Lo que pasa es que la configuracion del sftp que hace sshdroid es sftp://root@192.168.1.XX:2222 password 1234

      No se como usar el comando scp con el puerto 2222 y con password...
      Como seria el comando?

      Eliminar
    6. el puerto lo indicas con el parametro -p :
      scp origen user@destino:/ruta -p 2222
      no puedes poner el password automaticamente en el scp/ssh no existe la opcion ni existira, ppr eso ssh/scp es de las cosas mas seguras que hay en esta vida. Para que lo copie sin que te pida clave, tienes que usar la clave compartida. Busca un poco en plan "ssh sin clave" y si no lo consigues, avisame y pongo un post, que seguro que a mas de uno le interesa.

      Eliminar
  6. Hola, muy bueno tu blog, estoy aprendiendo un montón y mi raspi casi saca humo con todo lo que sabe hacer ya. en mi caso instale los altavoces directamente a la raspi i reproduzco con ellos. estoy probando el despertador con las modificaciones de Rumoku y no puedo ejecutarlo, estos son los errores:
    /usr/local/bin/maximafm-temperatura-tareas.sh: línea 88: EOF inesperado mientras se buscaba un `'' coincidente
    /usr/local/bin/maximafm-temperatura-tareas.sh: línea 91: error sintáctico: no se esperaba el final del fichero

    ResponderEliminar