mlrc(歌词脚本,支持很多播放器哦 :) 7月5日更新)

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
solcomo
帖子: 2838
注册时间: 2007-04-25 13:12

#16

帖子 solcomo » 2008-05-17 23:42

如骨头兄所愿 :em04
♜♞♝♛♚♝♞♜
♟♟♟♟♟♟♟♟
♙♙♙♙♙♙♙♙
♖♘♗♕♔♗♘♖

☠☯⚔⚓☣☦☃☕
☹☻☪☭☬⚖⚛⚜
ℜℳℬ™ ℋℯℓ℘ ℳℭ
sƂɐʍ рǀɹoʍ əɥʇ oS
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#17

帖子 xiooli » 2008-05-18 23:25

哈哈希望lz表认为偶来抢生意啊:
我给改了下,
1, 下载歌词从百度下了,准确率要高些。那个搜狗真是,昨天下了会儿居然怀疑我恶意批量下载,还要输入验证码 :em36
2, 显示匹配的歌词的代码也用使用了另外的办法,不用再生成很多tmp文件了。
3, 照顾了UTF-8(不只中文的utf-8)locale和GB的locale。
4, 添加了一段删除dos符号的代码。
抛砖引玉啦。

源代码:

代码: 全选

#!/bin/bash 

LRCDIR=~/.lyrics
[ ! -d $LRCDIR ] && mkdir $LRCDIR
#获取正在播放歌曲名字的函数
GETNAME(){ 
	#获取mpc正在播放的歌曲名字,去掉后缀(.mp3、.wma等)
	echo $(mpc playlist | grep ">" | sed -e 's/.*)\ //g;s/\..*//g')
}
#下载歌词的函数
DOWNLRC(){ 
	[ -d $TMPDIR ] || mkdir -p  $TMPDIR
	NM=$(GETNAME)
	#判断当前locale,utf-8的locale将要使用编码转换
	[ `locale |grep "LANG=.*UTF-8"` ] && lang=1
	#将歌曲名字转换为urlencode,utf-8的locale必须先转换为gb的编码
  	if [ $lang ];then
		#od的输出为每行16组,如果太长则会截断成两行,故而应该删除可能出现的换行符。
    		gb=`echo "$NM" | iconv -c -f utf-8 -t gb2312 | od -t x1 -A n |tr "\n" " " |tr " " % |sed 's/%%/%/g'`
  	else
    		gb=`echo "$NM" | od -t x1 -A n |tr "\n" " " |tr " " % |sed 's/%%/%/g'`
  	fi
	#从百度的歌词搜索里面找出当前歌曲的歌词下载页
  	wget "http://mp3.baidu.com/m?f=ms&tn=baidump3lyric&ct=150994944&lf=2&rn=10&word="$gb"&lm=-1"\
	  -O /dev/shm/lrc_file  -T 10 -q
  	#将所有的歌词文件的链接地址保存到一个数组里面,如果第一链接没有下载成功的话继续下载下一链接。
	LINKS=(`cat /dev/shm/lrc_file | grep -i "<div style=\"word-break:break-all\"" | awk -F"\"" '{print $4}'`)
	let lk_n=0
  	while [ ${LINKS[0]} ] && [ $lk_n -lt ${#LINKS[@]} ] && [ ! -s $LRCDIR/"$NM".lrc ];do
		if [ $lang ];then
			wget "${LINKS[$lk_n]}" -O /dev/shm/lrctmp  -T 5 -t 2 -q
			[ -s /dev/shm/lrctmp ] && iconv -f gb2312 -t utf-8 -c /dev/shm/lrctmp -o $LRCDIR/"$NM".lrc
			let lk_n=$lk_n+1
		else
			wget "${LINKS[$lk_n]}" -O $LRCDIR/"$NM".lrc  -T 5 -t 2 -q
			let lk_n=$lk_n+1
		fi
		[ -s $LRCDIR/"$NM".lrc ] && sed -i'' "s/\r/\n/g" $LRCDIR/"$NM".lrc #去掉dos字符
		> /dev/shm/lrctmp
	done
}
#lrc文件处理:将文件编上行号、仅提取出时间信息,一行中有多个时间的把每个时间断到下一行但是前面的行号不变
#这样的话,以后按照时间去搜索歌词行就不会出错
LRC_SPLIT() {
	cat $LRCDIR/"$NM".lrc -n |grep "\[[0-9]" |while read LINE0
	do
		n=`echo $LINE0 |grep " " |awk -F" " '{print $1}'`
		[ $n ] && num0=$n
		echo $LINE0 |sed "s/\]\[/@/g;s/\[//g" \
		|sed "s/@/\n$num0"\ "/g" |sed "s/:0/:/g"
	done    |sed "s/\ 0/\ /g;s/\..*//g;s/\].*//g" >/dev/shm/lrc_time.list 
		#/dev/shm相当于是直接建立在内存中的文件夹,把小的临时文件放里面可以减少对硬盘的读写,加快速度
}
#取得当前播放时间,找到并返回与其最贴近的歌词时间(小于当前播放的时间),可以根据此时间来搜索并显示歌词
FIND_LRC_TIME() {
	pltm=`mpc |grep / | awk -F" " '{print $3}' |awk -F"/" '{print $1}'`
	let tmp=-1
	let pltm_min=`echo $pltm |sed "s/:.*//g"`
	let pltm_sec=`echo $pltm |sed "s/.*://g;s/^0//g"`
	for i in `cat /dev/shm/lrc_time.list |grep "$pltm_min:"`;do
		let lrctm_sec=`echo $i |sed "s/.*://g"`
		if [ $tmp -lt $pltm_sec ] && [ $tmp -lt $lrctm_sec ] && [ $pltm_sec -ge $lrctm_sec ];then
			let tmp=$lrctm_sec 
		fi
	done
	echo "$pltm_min:$tmp"
}
#显示歌词的函数
DISPLAY() {
	clear
	LRC_SPLIT
	line0=0
	let n=0
	tmp0=0
	tmp1=$(FIND_LRC_TIME) 
	echo  -e "\033[;32m****** $NM ****** \033[0m "
	cp $LRCDIR/"$NM".lrc /dev/shm/lrc_tmp
	#当播放的歌是同一首歌曲时显示歌词
	while 	[ $(echo "$NM" |sed 's/\ /@/g') = $(echo "$(GETNAME)" |sed 's/\ /@/g') ] &&\
		[ -s $LRCDIR/"$NM".lrc ];do
		[ `mpc |grep playing |sed 's/ //g'` ] || break 			#判断播放状态,停止播放时跳出程序
		lrc_line=`cat /dev/shm/lrc_time.list |grep -m 1 -w $tmp1 |sed "s/\ .*//g"` && tmp1=$(FIND_LRC_TIME) 
		[ $lrc_line ] && [ $line0 != $lrc_line ] && words=`cat /dev/shm/lrc_tmp -n |sed "s/\[.*\]/@/g" \
		|grep -w $lrc_line |sed "s/.*@/ /g"` && line0=$lrc_line && let n=$n+1 && echo $words
		[ $n -eq 5 ] && clear && echo  -e "\033[;32m****** $NM ****** \033[0m " && echo $words && let n=0
		sleep 0.5
	done
	NM=$(GETNAME)
}

#*****main******
NM0="str"
let dn=0
while [ `mpc |grep playing |sed 's/ //g'` ];do
	NM=$(GETNAME) 
	if [ ! -s $LRCDIR/"$NM".lrc ];then
		[ $dn -le 3 ] && DOWNLRC && let dn=$dn+1 #下载失败时,最多重复下载3次
		[ ! -s $LRCDIR/"$NM".lrc ] && [ $(echo "$NM0" |sed 's/\ /@/g') != $(echo "$(GETNAME)"|sed 's/\ /@/g') ]\
		&& clear && echo -e "\033[;32m****** $NM ****** \033[0m" \
		&& echo "Lrc file not found!" && NM0=$NM && let dn=0
	else 
		clear 
		sed -i'' "s/\r/\n/g" $LRCDIR/"$NM".lrc #去掉dos字符
		DISPLAY 
		let dn=0
	fi
	sleep 0.5
done
附件
lrcshow.tar.gz
(2.29 KiB) 已下载 362 次
上次由 xiooli 在 2008-05-22 9:54,总共编辑 3 次。
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#18

帖子 xiooli » 2008-05-18 23:26

来张图:
附件
Screenshot.png
thword
帖子: 119
注册时间: 2007-04-09 12:19

#19

帖子 thword » 2008-05-19 10:58

赞一个 :em76
头像
solcomo
帖子: 2838
注册时间: 2007-04-25 13:12

#20

帖子 solcomo » 2008-05-19 11:02

脚本就是要靠更多人努力才能达到最好的效果嘛
:shock: 恶意批量下载...可能是我歌少...没遇到过...
♜♞♝♛♚♝♞♜
♟♟♟♟♟♟♟♟
♙♙♙♙♙♙♙♙
♖♘♗♕♔♗♘♖

☠☯⚔⚓☣☦☃☕
☹☻☪☭☬⚖⚛⚜
ℜℳℬ™ ℋℯℓ℘ ℳℭ
sƂɐʍ рǀɹoʍ əɥʇ oS
头像
yaoms
帖子: 4952
注册时间: 2007-10-19 14:51
来自: 深圳

#21

帖子 yaoms » 2008-05-19 11:06

solcomo 写了:yaoms,没找到这方面的资料,不知道具体怎么实现啊..
sudo apt-get install gnome-osd

做成插件,有人不喜欢osd..
Nothing 有事请发邮件到 yms541 AT gmail.com
alias 爱慕颇雷尔='mplayer'
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#22

帖子 xiooli » 2008-05-22 10:01

哈哈,又改了下代码,可以在第一链接没有下载到歌词的情况下再从第下一链接下载,还改正了当歌名太长时转换成urlencode出错的问题,改正了下载失败一直不停下载的问题,限定了最多下载重试次数。 :D :D
Joolix live OS: http://joolix.com

代码: 全选

dpkg -l|awk '/^rc/{print $2}'|sudo xargs dpkg -P
头像
solcomo
帖子: 2838
注册时间: 2007-04-25 13:12

#23

帖子 solcomo » 2008-05-22 10:32

xiooli 写了:改正了当歌名太长时转换成urlencode出错的问题
:shock: 我还正要说这个呢...
♜♞♝♛♚♝♞♜
♟♟♟♟♟♟♟♟
♙♙♙♙♙♙♙♙
♖♘♗♕♔♗♘♖

☠☯⚔⚓☣☦☃☕
☹☻☪☭☬⚖⚛⚜
ℜℳℬ™ ℋℯℓ℘ ℳℭ
sƂɐʍ рǀɹoʍ əɥʇ oS
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#24

帖子 xiooli » 2008-05-22 10:37

solcomo 写了:
xiooli 写了:改正了当歌名太长时转换成urlencode出错的问题
:shock: 我还正要说这个呢...
哈哈,我也是昨天才发现这个问题的。 :D
头像
fengjie
帖子: 130
注册时间: 2008-03-19 14:20

#25

帖子 fengjie » 2008-05-22 12:25

很好,很强大,你们太高手啦,支持了
主板:ASUS P8Z77-V
CPU:Intel 酷睿i3 3200
内存:ADTA DDRⅢ 1600 8G
显卡:Intel® HD Graphic
声卡:Realtek ALC 892
有线网卡:Intel® 82579V
无线网卡:Qualcomm Atheros AR9485
硬盘:WDC WD6401AALS
电源:长城ATX-350SD静音大师
显示器:Samsung S24A350H
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#26

帖子 xiooli » 2008-05-26 17:06

osd模式脚本(仅单独osd显示模式,没有终端模式)

代码: 全选

#!/bin/bash 

LRCDIR=~/.lyrics
[ ! -d $LRCDIR ] && mkdir $LRCDIR
#获取正在播放歌曲名字的函数
GETNAME(){ 
	#获取mpc正在播放的歌曲名字,去掉后缀(.mp3、.wma等)
	echo $(mpc playlist | grep ">" | sed -e 's/.*)\ //g;s/\..*//g')
}
#下载歌词的函数
DOWNLRC(){ 
	[ -d $TMPDIR ] || mkdir -p  $TMPDIR
	NM=$(GETNAME)
	#判断当前locale,utf-8的locale将要使用编码转换
	[ `locale |grep "LANG=.*UTF-8"` ] && lang=1
	#将歌曲名字转换为urlencode,utf-8的locale必须先转换为gb的编码
  	if [ $lang ];then
		#od的输出为每行16组,如果太长则会截断成两行,故而应该删除可能出现的换行符。
    		gb=`echo "$NM" | iconv -c -f utf-8 -t gb2312 | od -t x1 -A n |tr "\n" " " |tr " " % |sed 's/%%/%/g'`
  	else
    		gb=`echo "$NM" | od -t x1 -A n |tr "\n" " " |tr " " % |sed 's/%%/%/g'`
  	fi
	#从百度的歌词搜索里面找出当前歌曲的歌词下载页
  	wget "http://mp3.baidu.com/m?f=ms&tn=baidump3lyric&ct=150994944&lf=2&rn=10&word="$gb"&lm=-1"\
	  -O /dev/shm/lrc_file  -T 10 -q
  	#将所有的歌词文件的链接地址保存到一个数组里面,如果第一链接没有下载成功的话继续下载下一链接。
	LINKS=(`cat /dev/shm/lrc_file | grep -i "<div style=\"word-break:break-all\"" | awk -F"\"" '{print $4}'`)
	let lk_n=0
  	while [ ${LINKS[0]} ] && [ $lk_n -lt ${#LINKS[@]} ] && [ ! -s $LRCDIR/"$NM".lrc ];do
		if [ $lang ];then
			wget "${LINKS[$lk_n]}" -O /dev/shm/lrctmp  -T 5 -t 2 -q
			[ -s /dev/shm/lrctmp ] && iconv -f gb2312 -t utf-8 -c /dev/shm/lrctmp -o $LRCDIR/"$NM".lrc
			let lk_n=$lk_n+1
		else
			wget "${LINKS[$lk_n]}" -O $LRCDIR/"$NM".lrc  -T 5 -t 2 -q
			let lk_n=$lk_n+1
		fi
		[ -s $LRCDIR/"$NM".lrc ] && sed -i'' "s/\r/\n/g" $LRCDIR/"$NM".lrc #去掉dos字符
		> /dev/shm/lrctmp
	done
}
#lrc文件处理:将文件编上行号、仅提取出时间信息,一行中有多个时间的把每个时间断到下一行但是前面的行号不变
#这样的话,以后按照时间去搜索歌词行就不会出错
LRC_SPLIT() {
	cat $LRCDIR/"$NM".lrc -n |grep "\[[0-9]" |while read LINE0
	do
		n=`echo $LINE0 |grep " " |awk -F" " '{print $1}'`
		[ $n ] && num0=$n
		echo $LINE0 |sed "s/\]\[/@/g;s/\[//g" \
		|sed "s/@/\n$num0"\ "/g" |sed "s/:0/:/g"
	done    |sed "s/\ 0/\ /g;s/\..*//g;s/\].*//g" >/dev/shm/lrc_time.list 
		#/dev/shm相当于是直接建立在内存中的文件夹,把小的临时文件放里面可以减少对硬盘的读写,加快速度
}
#取得当前播放时间,找到并返回与其最贴近的歌词时间(小于当前播放的时间),可以根据此时间来搜索并显示歌词
FIND_LRC_TIME() {
	pltm=`mpc |grep / | awk -F" " '{print $3}' |awk -F"/" '{print $1}'`
	let tmp=-1
	let pltm_min=`echo $pltm |sed "s/:.*//g"`
	let pltm_sec=`echo $pltm |sed "s/.*://g;s/^0//g"`
	for i in `cat /dev/shm/lrc_time.list |grep "$pltm_min:"`;do
		let lrctm_sec=`echo $i |sed "s/.*://g"`
		if [ $tmp -lt $pltm_sec ] && [ $tmp -lt $lrctm_sec ] && [ $pltm_sec -ge $lrctm_sec ];then
			let tmp=$lrctm_sec 
		fi
	done
	echo "$pltm_min:$tmp"
}
#显示歌词的函数
OSD_SHOW() {
	gnome-osd-client -f "<message id='myplugin' osd_fake_translucent_bg='off'>`echo "$*"`</message>" 
}
DISPLAY() {
	LRC_SPLIT
	line0=0
	let n=0
	tmp1=$(FIND_LRC_TIME) 
	NM=$(GETNAME)
	OSD_SHOW "****$NM****"
	sleep 1
	cp $LRCDIR/"$NM".lrc /dev/shm/lrc_tmp
	while [ $(echo "$NM" |sed 's/\ /@/g') = $(echo "$(GETNAME)" |sed 's/\ /@/g') ] &&\
		[ -s $LRCDIR/"$NM".lrc ];do
		[ `mpc |grep playing |sed 's/ //g'` ] || break 			#判断播放状态,停止播放时跳出程序	
		lrc_line=`cat /dev/shm/lrc_time.list |grep -m 1 -w $tmp1 |sed "s/\ .*//g"` && tmp1=$(FIND_LRC_TIME) 
		[ -s $LRCDIR/"$NM".lrc ] && [ $lrc_line ] && [ $line0 != $lrc_line ] && words=`cat /dev/shm/lrc_tmp -n \
		|sed "s/\[.*\]/@/g" |grep -w $lrc_line |sed "s/.*@/ /g"` && OSD_SHOW $words && line0=$lrc_line && let n=$n+1
		sleep 0.5
	done
	NM=$(GETNAME)
}
#*****main******
NM0="str"
let dn=0
while [ `mpc |grep playing |sed 's/ //g'` ];do
	NM=$(GETNAME) 
	if [ ! -s $LRCDIR/"$NM".lrc ];then
		[ $dn -le 3 ] && DOWNLRC && let dn=$dn+1 #下载失败时,最多重复下载3次
		[ ! -s $LRCDIR/"$NM".lrc ] && [ $dn -eq 3 ] && OSD_SHOW "$NM:未找到lrc文件"
	else 
		sed -i'' "s/\r/\n/g" $LRCDIR/"$NM".lrc #去掉dos字符
		DISPLAY
		let dn=0
	fi
	sleep 0.5
done
附件
lrcosd.tar.gz
解压chmod +x ./lrcosd然后./lrcosd运行
(2.29 KiB) 已下载 245 次
头像
solcomo
帖子: 2838
注册时间: 2007-04-25 13:12

#27

帖子 solcomo » 2008-05-26 17:14

osd效果还是不错吧 :lol:
♜♞♝♛♚♝♞♜
♟♟♟♟♟♟♟♟
♙♙♙♙♙♙♙♙
♖♘♗♕♔♗♘♖

☠☯⚔⚓☣☦☃☕
☹☻☪☭☬⚖⚛⚜
ℜℳℬ™ ℋℯℓ℘ ℳℭ
sƂɐʍ рǀɹoʍ əɥʇ oS
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#28

帖子 xiooli » 2008-05-26 17:20

图:
ps:gnome-osd is needed
附件
Screenshot.png
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#29

帖子 xiooli » 2008-05-26 17:21

solcomo 写了:osd效果还是不错吧 :lol:
哈哈,最初不知道那个是什么东东,待得试了下就忍不住了 :D ,很好玩啊。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#30

帖子 eexpress » 2008-05-26 20:43

额,居然是反复扫描的。要是使用dbus通知机制就好哦。那样,标准支持dbus的播放器,就都等于有外挂了。就像gnome-osd那样。
目前,只知道看man
dbus-cleanup-sockets dbus-launch dbus-send
dbus-daemon dbus-monitor dbus-uuidgen
支持你们试试。
● 鸣学
回复