lrcdis不能用了?---mpd歌词脚本【11/08/07 更新,支持gnome-OSD】

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
wiewi
帖子: 628
注册时间: 2008-11-20 22:50
系统: ArchLinux

lrcdis不能用了?---mpd歌词脚本【11/08/07 更新,支持gnome-OSD】

#1

帖子 wiewi » 2011-07-21 22:56

很长时间没听歌,最近心血来潮打算听听,发现以前听歌最佳伴侣--lrcdis(感谢几位大牛贡献)不好用了,貌似是网站版式更新了下载不到歌词?具体不记得了。
gnome-osd显示歌词一直很喜欢,可是它在我电脑上用不了。
gnome-osd挂了,意味着以前用过的osd-lyrics也不能用了,没有跟MPD配套的歌词显示插件,搜也没搜到好用的脚本,自己拿shell整了一个,终端显示,凑活用着。
========================================================
2011/08/07 更新
发现gnome-osd不是不能用,是不能像以前那样直接gnome-osd-client "Text"就可以显示,现在的版本会报错,但是运行manpage里的例子,它还是能工作的,参考了lrcdis,顺手把自己用的这个脚本整了整,重新贴下吧。
[bash]
[liwei@Arch ~] $ cat bin/mpdlyric
#!/bin/bash
# Show lyric when playing music with mpd.
# 2011/07/17
# wiewi,[email protected]
# Download function!! # Finished on July 20,Wednesday

# Updated on 2011/08/07
# Three ways of displaying lyrics
# 1.Gnome-OSD (Default) # 需要安装gnome-osd
# 2.Echo text in terminal
# 3.Redirect lyric to text file ($HOME/lyric.out)
# Work together with conky,add '${execi -1 tail -n 1 $HOME/tmp/lyric.out}'in conkyrc)

# 已知问题:
# 1.Note that when the text line is very long, last several words will not be displayed in conky.
# 歌词如果太长,conky将只能显示前面部分,除非你的conky很宽。
# 有个老外的python的脚本可以根据宽度断行的,我这bash的懒得弄了~~
# 2.Gnome-OSD显示英文歌词时,有时候歌词显示位置跟指定位置有一行的偏差,感觉像显示了换行符一样,暂时还没有搞定。

# Thanks to all the authors of the famous bash script 《lrcdis》 where some lines of code here come from.

##########################
# Lyric dir
LYRIC=$HOME/.lyrics

# Temp files
SEARCH=$HOME/tmp/search
OUT=$HOME/tmp/lyric.out

# Display timeout(for Gnome-OSD & notify-OSD)
Timeout=5000

##########################
# Gnome-OSD显示方式设置
# Span size
Size=20000
# Foreground (字体颜色) while/black/blue/green/yellow/...
Foreground=blue
# 动作 on/off
Animations=off
# 垂直位置 top/center/bottom
Vposition=bottom
# 水平位置 left/center/right
Halignment=left
#########################

# Player Status
STATUS=$(mpc status| sed -n '2p' | awk '{print $1}' | sed 's/[^a-zA-Z]//g')

GetInfo(){

# Song info
SONG=$(mpc --format %title% | sed -n '1p' 2>/dev/null)
ARTIST=$(mpc --format %artist% | sed -n '1p' 2>/dev/null)
NAME=$(echo $SONG | sed "s/$ARTIST//" 2>/dev/null | sed 's/\-//g'|sed 's/(.*)//g')

# LRC file
FILE=$LYRIC/`echo $NAME | tr -d ' '`.lrc
}

Download(){
# 从gougou搜索歌词文件并下载
#gougou will lead to the site used below

GetInfo;

[ -f "$SEARCH" ] && rm -f $SEARCH

# “歌曲名 歌手” 搜索 管道写法参考lrcdis脚本
wget -c -T 10 "http://www.lrc123.com/?keyword=$NAME $ARTIST&" -O $SEARCH > /dev/null 2>&1 | iconv -f GBK

URL=`cat $SEARCH | grep -B1 '下载' | grep color | sed -n '1p'| sed 's/<[^>]*>//g' | tr -d ' '|sed 's/\\r//'`

# 第一种方式搜索不到,使用“歌曲名” 搜索
if [ -z "$URL" ];then
wget -c -T 10 "http://www.lrc123.com/?keyword=$NAME&" -O $SEARCH > /dev/null 2>&1 | iconv -f GBK
fi
URL=`cat $SEARCH | grep -B1 '下载' | grep color | sed -n '1p'| sed 's/<[^>]*>//g' | tr -d ' '|sed 's/\\r//'`

if [ -z "$URL" ];then
# 两种方式都搜索不到
Display "歌词搜索失败!" # && exit 1
SONG_PREV=$(mpc --format %title% | sed -n '1p')
Wait;

else
# 有搜索结果,那么下载歌词文件
wget -c -T 10 $URL -O "$FILE" > /dev/null 2>&1| iconv -f GBK
fi

}

Wait(){

# 对于下载不到歌词的曲目,每隔1秒重新读取播放器信息,一旦切换到下首,则重新尝试Download歌词
# 有两种情况: 1 可以得到歌曲信息,但是搜索不到符合条件的lrc
# 2 歌曲信息为空,无法搜索

while :
do
sleep 1
# 获取当前播放信息
GetInfo
# 有歌曲切换,检查文件是否存在,或者尝试下载,然后显示歌词
if [ -n "$SONG" -a "$SONG_PREV" != "$SONG" ];then
SONG_PREV=$SONG
[ -f "$FILE" ] || Download;
ShowLyric $Option;
fi
done
}

# 将showlyric得到的$TEXT用指定的方式显示
Display(){
case $Option in
# notification方式,显示不太准确
#-n) notify-send -t $Timeout $1
# ;;

# 输出到文本文件
-o) echo "$1" >> $OUT
;;
# Gnome-osd 显示
-g) gnome-osd-client -f "<message id='mpdlyric' osd_fake_translucent_bg='off' osd_vposition='$Vposition' animations='$Animations' hide_timeout='$Timeout' osd_halignment='$Halignment'><span size='$Size' foreground='$Foreground'>`echo -n $1`</span></message>"
;;
# 最简单的方式,终端文本输出
-t) echo $1
;;
*) gnome-osd-client -f "<message id='mpdlyric' osd_fake_translucent_bg='off' osd_vposition='$Vposition' animations='$Animations' hide_timeout='$Timeout' osd_halignment='$Halignment'><span size='$Size' foreground='$Foreground'>`echo -n $1`</span></message>"
;;
esac
}



ShowLyric(){
# 进入显示歌词的循环前,显示当前播放曲名
Display "===== $NAME - $ARTIST =====";


# 显示歌词的循环
while :
do
# 若是歌曲在sleep 0.3之间切换,那么歌曲名称等信息没有更新,下面取得TEXT的步骤可能出错,所以需要重新生成歌曲信息
GetInfo
[ -z "$SONG" ] && Display "歌曲信息不全!" && Wait;
if [ ! "`file $FILE | grep -i utf-8`" ];then
iconv -f GBK -t UTF-8 $FILE -o $FILE
fi
TIME=`mpc status | grep '/' | awk -F '/' '{print $2}' | awk '{print $2}'`
TEXT=`[ -f "$FILE" ] && cat "$FILE" | grep $TIME | sed 's/\[[^]]*]//g'|sed 's/\\r//'`
CURRENT=`mpc current`

if [ -z "$PREV" -o "$CURRENT" = "$PREV" ];then
PREV=`mpc current`

# 换到下一句歌词
if [ -n "$TEXT" -a "$TEXT" != "$TEXT_PREV" ];then
sleep 0.8
Display "$TEXT";

TEXT_PREV="$TEXT"
fi
# 歌曲切换
else
PREV=''
GetInfo
Display "===== $NAME - $ARTIST =====";

[ -f "$FILE" ] || Download;
continue
fi

# 等待0.3秒后进入下个循环
sleep 0.3

done
}

# 记录选项
Option="$1"
# 如果选择输出到文件,那么先删除以前的文件,避免文件过大
[ "$Option" = '-o' -a -f "$OUT" ] && rm -f "$OUT"

while :
do
case $STATUS in
playing) GetInfo
# 没有歌词就下载
[ -f "$FILE" ] || Download;
ShowLyric $Option;;
*) Display "MPD not running!" && exit 1;;
esac
done
[/bash]
2011-08-07-14-35-07.png
Gnome-OSD显示
Gnome-OSD显示
2011-08-07-13-37-05.png (5.58 KiB) 查看 1871 次
conky显示
conky显示
2011-08-07-14-07-00.png (8.37 KiB) 查看 1871 次
大概效果就是这样了,比较土,本人菜鸟,欢迎拍砖
上次由 wiewi 在 2011-08-07 14:39,总共编辑 3 次。
===我的小窝===
无聊吗?点我吧,楼主迫切期待你的光临~~
又一个轮子
------------------------------------
这年头,没有1000贴都不好意思见人了
------------------------------------
献丑不如藏拙
------------
头像
lexdene
帖子: 434
注册时间: 2010-02-21 16:19
来自: 大连
联系:

Re: lrcdis不能用了?

#2

帖子 lexdene » 2011-07-22 9:04

大牛。
膜拜。
yvmu
帖子: 54
注册时间: 2006-05-04 20:04

Re: lrcdis不能用了?

#3

帖子 yvmu » 2011-08-05 15:56

这个脚本真不错,我再改改,把播放器换成我喜欢的mocp,用MOC的直接拿去。

代码: 全选

#!/bin/bash

# Lyric dir
LYRIC=$HOME/.lyrics

# Temp files
SEARCH=$HOME/.lyrics/tmp

# Notify timeout
TIMEOUT=1000

# Player Status
STATUS=$(mocp -i | grep ^State | sed 's/State: //')

GetInfo(){

# Song info
SONG=$(mocp -i | grep ^Title | sed 's/Title: //')
ARTIST=$(mocp -i | grep ^Artist | sed 's/Artist: //')
NAME=$(mocp -i | grep ^SongTitle | sed 's/SongTitle: //')

# LRC file
FILE=$LYRIC/`echo $NAME | tr -d ' '`.lrc
}

Download(){
    # 从gougou搜索歌词文件并下载
    #gougou will lead to the site used below

    GetInfo;

    PERIOD=''
    [ -f "$SEARCH" ] && rm -f $SEARCH

    # “歌曲名 歌手” 搜索  管道写法参考lrcdis脚本
    wget -c -T 10 "http://www.lrc123.com/?keyword=$NAME $ARTIST&" -O $SEARCH > /dev/null 2>&1 |  iconv -f GBK

    URL=`cat $SEARCH | grep -B1 '下载' | grep color | sed -n '1p'| sed 's/<[^>]*>//g' | tr -d ' '|sed 's/\\r//'`

    # 第一种方式搜索不到,使用“歌曲名” 搜索
    if [ -z "$URL" ];then
        wget -c -T 10 "http://www.lrc123.com/?keyword=$NAME&" -O $SEARCH > /dev/null 2>&1 | iconv -f GBK
    fi
    URL=`cat $SEARCH | grep -B1 '下载' | grep color | sed -n '1p'| sed 's/<[^>]*>//g' | tr -d ' '|sed 's/\\r//'`

    if [ -z "$URL" ];then
    # 两种方式都搜索不到
        echo "LRC not found!" # &&  exit 1
        SONG_PREV=$(mocp -i | grep ^Title | sed 's/Title: //')
        Wait;

    else
    # 有搜索结果,那么下载歌词文件
        wget -c -T 10 $URL -O "$FILE" > /dev/null 2>&1| iconv -f GBK
    fi

}

Wait(){
    # 对于下载不到歌词的曲目,每隔1秒重新读取播放器信息,一旦切换到下首,则重新尝试Download歌词
while :
do
   sleep 1
#   SONG=$(mpc --format %title% | sed -n '1p')
   GetInfo
   if [ "$SONG_PREV" != "$SONG" ];then
       SONG_PREV=$SONG
       [ -f "$FILE" ] || Download;
       ShowLyric;
   fi
done
}

#GetSecond(){
    # 得到形如4:24的时间的秒数
#min=`echo "$1" | cut -d ':' -f1`
#sec=`echo "$1" | cut -d ':' -f2`
#res=`echo "$min*60 + $sec" | bc`
#}


ShowLyric(){
#       [ -f "$FILE" ] || Download;
       #eval "$CMD" "\n$NAME - $ARTIST\n"
       echo -e "\n$NAME - $ARTIST\n"
#       notify-send "$NAME - $ARTIST"
       while :
       do
       if [ ! "`file $FILE | grep -i utf-8`" ];then
            iconv -f GBK -t UTF-8 $FILE -o $FILE
       fi
       TIME=$(mocp -i | grep ^CurrentTime | sed 's/CurrentTime: //')
       TEXT=$(cat "$FILE" | grep $TIME | sed 's/\[[^]]*]//g')
       CURRENT=$(mocp -i | grep ^CurrentSec | sed 's/CurrentSec: //')

       if [ -z "$PREV" -o "$CURRENT" = "$PREV" ];then
         PREV=$CURRENT

         # 换到下一句歌词
         if [ -n "$TEXT" -a "$TEXT" != "$TEXT_PREV" ];then
# Notify 方式有问题,歌词更新太慢,即使指定了timeout问题依旧
#       notify-send -t $TIMEOUT -- "$TEXT"
#              echo $TEXT
              sleep 0.8
              eval "$CMD"
              TEXT_PREV="$TEXT"
         fi
       # 歌曲切换
       else
              PREV=''
              GetInfo
             # eval "$CMD" "\n$NAME - $ARTIST\n"
#              echo -e "\n$NAME - $ARTIST\n"
#              notify-send "$NAME - $ARTIST"

              [ -f "$FILE" ] || Download;
              continue
       fi
         sleep 0.3
       done
}

case $1 in
    -n) CMD='notify-send -t $TIMEOUT --  $TEXT'
        ;;
    *)  CMD='echo $TEXT'
        ;;
esac

while :
do
case $STATUS in
    PLAY) GetInfo
             [ -f "$FILE" ] || Download;
             ShowLyric;;
    *) echo "MOC not running!" && exit 1;;
esac
done
头像
我就是我2
帖子: 1215
注册时间: 2008-12-13 10:55
来自: the Earth
联系:

Re: lrcdis不能用了?

#4

帖子 我就是我2 » 2011-08-06 13:35

决定了,我要回复这个帖子,并且尝试理解代码的意思!
苏东坡问佛印道:“人人皆念观世音菩萨,观世音菩萨念谁?”
佛印答道:“念观世音菩萨。”
苏东坡诧异:“为何亦念观世音菩萨?”
曰:“求人不如求己。”


dropbox 誰好奇,誰來點
勞碌一生又如何,虛度一生又如何,你過得開心嗎?人活著就要開心嘛!
yvmu
帖子: 54
注册时间: 2006-05-04 20:04

Re: lrcdis不能用了?---mpd歌词脚本【11/08/07 更新,支持gnome-OSD】

#5

帖子 yvmu » 2011-08-10 15:14

老实说,这个shell脚本负载有点高。用Perl重写了下,有需要的同学拿去。

代码: 全选

#!/usr/bin/perl

use strict;
use warnings;
use LWP::Simple qw ($ua get);
use Encode;

$ua->timeout(2);

my %play;
my $SongTitle="";
my $Artist="";
my $lrc="";
my $show="";

sub mocp{

    my $info=$_[0];
    my $i=`mocp -i`;

    if ($i=~/^State: (.+?)$/m){
	$$info{State}=$1;
    }
    if ($i=~/^Artist: (.+?)$/m){
	$$info{Artist}=$1;
    }else{
	$$info{Artist}="";
    }
    if ($i=~/^SongTitle: (.+?)$/m){
	$$info{SongTitle}=$1;
    }else{
	$$info{SongTitle}="";
    }
    if ($i=~/^CurrentTime: (.+?)$/m){
	$$info{CurrentTime}=$1;
    }

}

sub wget{

    my $url=$_[0];
    my $g;
    for(my $i=0;$i<5;$i++){
	if ($g=get $url){
	    return $g;
	}
    }

}

sub dl{

    my ($SongTitle,$Artist,$lrc)=@_;

    my $url="http://www.lrc123.com/?keyword=$SongTitle+$Artist&field=all";
    my $get=&wget($url);

    if ($get=~/<a href="([^"]+)">LRC/){
	$$lrc=&wget("http://www.lrc123.com".$1);
	return 1;
    }

    $url="http://www.lrc123.com/?keyword=$SongTitle&field=all";
    $get=get $url;

    if ($get=~/<a href="([^"]+)">LRC/){
	$$lrc=&wget("http://www.lrc123.com".$1);
	return 1;
    }

    return 0;
}

sub show{

    my $time=$_[0];
    if($lrc=~/$time.+?([^\]]+?)$/m){
	return $1
    }else{
	return 0;
    }
}

sub run{

    &mocp(\%play);


    if (!($play{SongTitle} eq $SongTitle) || !($play{Artist} eq $Artist)){

	$SongTitle=$play{SongTitle};
	$Artist=$play{Artist};

	if (!($SongTitle eq "")){
	    if (&dl($play{SongTitle},$play{Artist},\$lrc)){
		
		print "$SongTitle-$Artist\n";
		$lrc=encode("UTF-8",$lrc);
		
	    }else{
		print "no lrc!\n";
		$lrc=0;
	    }
	}
    }

    if ($lrc){
	if (&show($play{CurrentTime})){
	    my $new=&show($play{CurrentTime});
	    if (!($show eq $new)){
		$show=$new;
		print $show."\n";
	    }
	}
    }

    select (undef,undef,undef,0.5);
}

while(1){
    &run;
}
头像
_Fly
帖子: 145
注册时间: 2011-05-10 21:46

Re: lrcdis不能用了?---mpd歌词脚本【11/08/07 更新,支持gnome-OSD】

#6

帖子 _Fly » 2012-02-28 23:37

顶了 :em11
回复