Hola comunidad. ¿Un poco poético el título no? Pues nada, que hoy quiero compartir con ustedes mi método para hacer listas aleatorias para reproductores mp3.
Resulta que hace un tiempo me regalaron un reproductor de mp3 de los que reproduce todas las canciones que copias en su memoria. Me encanta escuchar música variada, pero escogerla ya es otro tema. Como casi todo programador soy bastante vago, así que decidí pasar el trabajo de escoger la música una sola vez. Tengo en mi computadora una carpeta que tiene muchísima música y no quería ir disco por disco diciendo que quería escuchar así que decidí hacer un script que lo hiciera por mi. Como ya podrán imaginar por el título del artículo vamos a programar en Python. Así que manos a la obra.
Paso 1
Decirle a nuestro script de donde va a sacar la música. Decidí hacer esto haciendo una lista de carpetas para que nos permite copiar música de diferentes orígenes.
folders = ['/media/data/musica/AC-DC/','/media/data/musica/Led Zeppelin/', '/media/data/musica/The Rolling Stones/']
Paso 2
Inicializamos algunos parámetros
allmp3 = [] #lista de canciones resultado del algoritmo limit = 300 #cantidad de canciones que queremos copiar destination = '/media/akiel/music/' #lugar donde queremos copiar las canciones count = limit #contador para poner el número del orden a las canciones en el destino
Paso 3
Ahora buscaremos en las carpetas seleccionadas todos los archivos mp3 para rellenar la lista allmp3
for folder in folders: for root, dirs, files in os.walk(folder): for i in files: if splitext(i)[1].upper() == '.MP3': allmp3.append(root+sep+i) print len(allmp3), 'mp3 files found'
Paso 4
Ya que tenemos todas las canciones en nuestra lista así que vamos a copiar los archivos aleatoriamente hacia nuestro dispositivo. Utilizaremos la función sample de Python para que nos devuelva un iterador con una muestra aleatoria de nuestra lista de música e iremos copiando una a una hacia el destino (destination)
for i in sample(allmp3,limit): print 'copy', i, destination+str(count)+' - '+basename(i) copyfile(i, destination+str(count)+' - '+basename(i)) count -= 1
Código Completo
Y eso fue todo. Aquí les dejo el código completo del script para que lo modifiquen a su gusto. Espero que resulte instructivo y como siempre: Happy Hacking!!!
# -*- coding: UTF-8 -*- import os from os.path import splitext, basename, sep from random import sample from shutil import copyfile folders = ['/media/data/musica/AC-DC/','/media/data/musica/Led Zeppelin/', '/media/data/musica/The Rolling Stones/'] allmp3 = [] limit = 300 destination = '/media/akiel/music/' count = limit for folder in folders: for root, dirs, files in os.walk(folder): for i in files: if splitext(i)[1].upper() == '.MP3': allmp3.append(root+sep+i) print len(allmp3), 'mp3 files found' for i in sample(allmp3,limit): print 'copy', i, destination+str(count)+' - '+basename(i) copyfile(i, destination+str(count)+' - '+basename(i)) count -= 1
Comentarios ( 24 )
Tio cuantas veces te mordieron esas serpientes??? jaja mola!
está interesante, pero prefiero coger el reproductor, “tirarle” tó la musica y darle random
Miralo, despues no pregunten por que no sale MoonLightDE :D.
Buen post
jajaja 100+
bueno el post pero me gusta que busque en toda la musica que tengo vaya zubieta 😉
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from os.path import splitext, basename, sep
from random import sample
from shutil import copyfile
folders,allmp3 = [‘/home/daniel/Music’],[]
destination = ‘/tmp/music/’
def main():
x,limit = 0,200
count = limit
while x != len(folders):
for root, dirs, files in os.walk(folders[x]):
for i in files:
if splitext(i)[1].upper() == ‘.MP3’:
allmp3.append(root+sep+i)
for i in dirs:
folders.append(root+sep+i)
x+=1
print len(allmp3), ‘mp3 files found’
for i in sample(allmp3,limit):
print ‘copy’, i, destination+str(count)+’ – ‘+basename(i)
copyfile(i, destination+str(count)+’ – ‘+basename(i))
count -= 1
return 0
if __name__ == ‘__main__’:
main()
También, para los interesados pueden echarle un vistazo a beets: the music geek’s media organizer (http://beets.readthedocs.org/):
1. Instalar beets. En Debian o Ubuntu por ejemplo: apt-get install beets.
2. Localizar el archivo de configuración ejecutando: beet config -p
3. Abrir el archivo que dio como salida y crear esta configuración mínima:
import:
copy: no
write: no
plugins: random
Nota:
– Los parámetros copy, (write/autotag) configuran la copia de los archivos importados y la modificación de sus metadatos respectivamente. En este caso los inhabilité para que no me modificara la colección que ya tengo.
– Se habilita el plugin random.
4. Luego se importa la música de dondequiera que esté -esto puede tardar en dependencia del tamaño de la colección-:
beet import /ruta/al/directorio/de/musica
5. Mostrar una lista aleatoria de canciones en formato mp3. En el ejemplo el parámetro -n configura la cantidad de canciones a mostrar -10 en este caso-:
beet random -n 10 -p -e path::’.mp3$’
6. Finalmente redireccionar la salida para un archivo m3u:
beet random -n 10 -p -e path::’.mp3$’ > MiLista.m3u
Una vez indexada la colección de música, se pueden hacer consultas más complejas (http://beets.readthedocs.org/en/v1.3.10/reference/query.html), como:
– Obtener una lista aleatoria de las canciones del año 2000:
beet random -n 10 -p -e path::’.mp3$’ year:2000 > Año2000.m3u
Y así encadenar la búsqueda con muchos más campos. Los campos disponibles se pueden ver ejecutando:
beet fields
Beets cuenta con una buena cantidad de complementos que pueden ver en http://beets.readthedocs.org/en/latest/plugins/
Viendo que no sale bien la sangría del import, para que se vea mejor, en el archivo de configuración, agregarlo así:
import: {copy: no, write: no, autotag: no}
plugins: random
Añadiendo resultados de una query a mocp, pa que después no digan que no puedo hacer lo que quiera desde el terminal 😛
beet ls artist:’arctic monkeys’ | xargs -d ‘\n’ mocp -a
Akiel…eres lo maximo!!!
Se acabaron las horas y horas de seleccionar musica para luego escucharla en orden alfabetico…
Ela problema de la aleatoriedad de la música es un poquito mas complicado según mi opinión. El primer problema es que sample y todas las candentes de “random” no hacen en realidad que la selección sea aleatoria, x varias cosas:
1. “Walk” recorre en profundidad, o sea si agregas recursivamente por orden las carpetas de música, un archivo en la carpeta de música 1, keda estadisticamente más cerca de uno de su misma carpeta, ke de otra. O sea, la muestra no está lo suficientemente dispersa. Lo que produce resultados más parecidos (por ejemplo, musica de un mismo álbum) para valores de random con diferencias pequeñas. Eso no es deseable.
2. Un algoritmo de selección aleatoria de música, no significa una buena selección de la música que se quiere escuchar. Eso está dado porque la música que escuchamos viene acompañada de un factor social, por ejemplo, en que horario del dia la escuchamos, en compañía de kien, los géneros que tienen que ver unos con otros. Es por eso que ya algunos reproductores recolectan sutilmente esos datos para conformar sus algoritmos de selección “aletoria” de música. Que al final no es más ke un algoritmo de IA de decisión x casos.
Puedes usar esos datos par mejorar tu algoritmo. No obstante es un problema y bien conocido y estudiado, pero muy interesante.
Saludos
Guille
Sí moonlight no salió fue sencillamente por estar programado por gente como él autor, que hace este script que está bastante malo y no le da pena hacerlo público. Yo creo que eso se puede hacer en una línea de Bash.
Además duplicar la música no es hacer un playlist
@Firvida
troll y pa joder más duplicándose. le vas a enseñar bash a los chamas también?
@efirvida
lee de nuevo la introducción al artículo y te darás cuenta de que si estoy hacindo una lista para un reproductor mp3 de alguna forma tengo que copiar las cosas para allá no?
@Akiel
#!/bin/bash
find $CARPETA_DE_MUSICA | grep -iE (mp3|wmv)$ |sort -R | tail -n $CANTIDAD_CANCIONES | while read FILE;
do
cp -v “$FILE” $DESTINO
done
Lo peor no es que tu script está malo, lo malo es que crees que por hacerlo eres un domador de serpientes.
@Akiel
Haz oído hablar del m3u?? hasta en la Wikipedia te lo puedes encontrar https://es.wikipedia.org/wiki/M3U la mayoría de los reproductores de musica lo usan para manejar los playlist
@Firvida
uhhhh q miedo! venga q te damos el premio al troll del mes y vete a joder a otro que cada vez que el sitio te deja publicar me llega un correo!
@efirvida
no lo entiendes todavía :-\
ademas tu triple ‘for’ deja mucho que desear los domadores de serpientes usamos “list comprehensions”
aquí va y todavía se puede mejorar
# -*- coding: UTF-8 -*-
import os
from random import sample
import subprocess
folders = [‘/media/efirvida/data/Music’]
limit = 300
playlist = ‘playlist.m3u’
allmp3 = [root + ‘/’ + i for folder in folders for root, dirs, files in os.walk(folder) for i in files if i.upper().endswith(‘MP3’)]
m3u = open(playlist, ‘w’)
m3u.writelines(‘#EXTM3U\n’)
[m3u.write(‘#EXTINF:-1,{0:s}\n{1:s}\n’.format(i.split(‘/’)[-1], i)) for i in sample(allmp3, limit)]
m3u.close()
subprocess.call([‘mplayer’, ‘-playlist’, playlist, ‘-shuffle’])
o así
import os
from random import sample
import subprocess
folders = [‘/media/efirvida/data/Music’]
limit = 300
playlist = ‘playlist.m3u’
open(playlist, ‘w’).writelines([‘#EXTM3U\n’]+[‘#EXTINF:-1,{0:s}\n{1:s}\n’.format(i.split(‘/’)[-1], i) for i in sample([root + ‘/’ + i for folder in folders for root, dirs, files in os.walk(folder) for i in files if i.upper().endswith(‘MP3’)], limit)])
subprocess.call([‘mplayer’, ‘-playlist’, playlist, ‘-shuffle’])
y por ultimo la version de 4 lineas vs 5 en bash
import os, subprocess, random
folders,limit,playlist = [‘/media/efirvida/data/Music’],300,’playlist.m3u’
open(playlist, ‘w’).writelines([‘#EXTM3U\n’]+[‘#EXTINF:-1,{0:s}\n{1:s}\n’.format(i.split(‘/’)[-1], i) for i in random.sample([root + ‘/’ + i for folder in folders for root, dirs, files in os.walk(folder) for i in files if i.upper().endswith(‘MP3’)], limit)])
subprocess.call([‘mplayer’, ‘-playlist’, playlist, ‘-shuffle’])
@efirvida
copiado textualmente de la documentación pero bueno si no te gusta siempre puedes hacer el tuyo y medirtela alante de todo el mundo. uh, felicidades campeón. eres el reductor\optimizador de código estrella del mes. fuegos artificiales, marcha con bombo y platillo.
es una lástima que ya no sea editor aquí
@Akiel
No se trata de reducir/optimizar de hecho mientras más comprimido más lento me funcionaba solo te enseñaba el poder de las comprensión de listas para que nunca más en tu vida uses n for anidados para crear una lista, al menos si quieres domar algo más grande que un gusano.
Por otro lado aprende a leer las recomendaciones y seguir los links, que no fui el primero que mencionó el m3u (@whippiii), antes mira de que se trata lo que te dicen y después habla, si lo probaste te habrás dado cuenta que como te decía no hacia falta duplicar la música, en tu script cuando lo corras n veces tendrás un playlist de n*300 canciones a no ser que las borres manualmente cada vez que quieras variar, sin hablar del espacio que estas inutilizando por no googlear “playlist file formats”
@bro
No entendiste bien el post el lo que hace es copiar pa su mp3 pa reproducir luego fuera de la pc. Lo otro fue que me tiraste con lo de Bash 5 lineas lo deje asi pa que las niñas entendieran el código aquí te lo dejo un poco más optimizado ‘suck on this’:
find $DIR | grep -iE (mp3|wmv)$ |sort -R | tail -n 300 | while read F; do cp -v “$F” “$D”; done
ahh ahora entiendo, que me disculpen entonces, pero bueno como era para domadores de serpientes debió haber sido así
import os, random, shutil;folders,limit,destination = [‘CARPETAS DE MUSICA’],300,’CARPETA DESTINO’;map(lambda x:shutil.copy(x,destination),[file for file in random.sample([root + os.path.sep + i for folder in folders for root, dirs, files in os.walk(folder) for i in files if i.upper().endswith(‘MP3’)], limit)])
y bueno la versión en una sola linea de mi anterior con reproducción en background y todo, para las niñas
import os, subprocess, random;folders,limit,playlist = [‘CARPETA DE MUSICA’],300,’/tmp/playlist.m3u’;open(playlist, ‘w’).writelines([‘#EXTM3U\n’]+[‘#EXTINF:-1,{0:s}\n{1:s}\n’.format(i.split(‘/’)[-1], i) for i in random.sample([root + ‘/’ + i for folder in folders for root, dirs, files in os.walk(folder) for i in files if i.upper().endswith(‘MP3’)], limit)]);subprocess.call([‘screen’,’-d’,’-m’,’mplayer’, ‘-playlist’, playlist, ‘–shuffle’,’–quiet’])
lo que estaba haciendo era esto:
find $DIR | grep -iE “(mp3|wmv)”$ |sort -R | tail -n 300| while read F; do echo “$F” >> playlist; done; screen -d -m mplayer -playlist playlist;