Python 库使用实例:MP3播放器

对于Python内置的标准库,我们可以直接在程序中import后使用,而大量的第三方库需要我们安装后才能使用。在Python中可以使用pip命令安装第三方库,也可以使用easy_install工具进行安装,建议使用pip。pip还支持卸载操作,当我们卸载某一个模块时,直接使用

pip uninstall xx

即可。今天以pymedia为例,介绍第三方库的安装使用。

1.Pymedia安装

Pymedia是一个基于C/C++、Python实现的多媒体模块,可以对包括MP3/ogg/avi等多媒体格式文件进行编解码和播放,基于ffmpeg提供了简单的Python接口。官方的Mymedia已经很精没有更新,只支持Python2.6,不支持Python2.7和Python3.0,我们可以到http://www.lfd.uci.edu/~gohlke/pythonlibs/#pymedia 网站下载非官方的库使其支持Python2.7,如果电脑为64位系统,需要下载64位的安装文件:pymedia-1.3.7.3-cp27-none-win_amd64.whl,Python中可以使用wheel工具来安装.whl文件,首先使用pip安装wheel,然后进行安装即可:

2.MP3文件介绍

MP3文件是一种音频压缩格式,它通过对采样后的音频数据通过压缩,生成MP3这种格式的声音文件。在MP3播放过程中,首先会对音频数据进行解码操作,最后还原后的音频数据送往数模转换,还原成自然的声音。
MP3文件主要分三部分:AG_V2(ID3V2),Frame, TAG_V1(ID3V1)

  • ID3V2包含了作者、作曲、专辑等信息,长度不固定。
  • Frame:音频数据是由一帧一帧的数据组成的,一帧数据的长度是4个字节,而Frame正是存储音频数据帧的部分。

因为AG_V2的长度不固定,所以我们无法确定一个MP3文件中第一帧数据从什么地方开始,在实际的操作过程中,需要进行解析操作。

3.音乐播放原理

解码后的音频数据通过系统送往声卡,声卡通过数模转换,然后通过扬声器就可以将音乐放大播放出来。在Linux系统中,音频通过ALSA音频子系统,一般会留给应用层mixer和dsp两个设备节点。应用程序可以通过mixer来控制播放的一些参数:比如音量、声道等。通过网设备节点dsp读写数据就可以实现录音和放音操作。

4.MP3播放音乐过程

首先,新建一个mp3player.py文件:

# -*- coding: utf-8 -*-
import pymedia.audio.acodec as acodec
import pymedia.muxer as muxer
import pymedia.audio.sound as sound
import time
import sys
def play_mp3(name):
    dm = muxer.Demuxer('mp3')
    snd = None
    dec = None
    s = " "
    f = open(name, 'rb')
    data = f.read(10000)
    while True:
        if len(data):
            frames = dm.parse(data)
            for frame in frames:
                if dec == None:
                    dec = acodec.Decoder(dm.streams[0])
                r = dec.decode(frame[1])
                if r and r.data:
                    if snd == None:
                        snd = sound.Output(r.sample_rate, r.channels, sound.AFMT_S16_LE)
                    snd.play(r.data)
        else:
            break
        data = f.read(10000)

    while snd.isPlaying():
        time.sleep(0.05)
if len(sys.argv) != 2:
    print "Usage: mp3player <filename>"
else:
    play_mp3(sys.argv[1])

然后在当前MP3player.py文件的目录下放置一个dadi.mp3文件,通过DOS进入到当前目录

F:\python\python_proj>python mp3.py dadi.mp3

即可播放。

代码分析

1.获取MP3数据

要播放一段音乐,首先要打开一个文件,读取数据才能进行相关操作。在Python中可以使用open函数打开一个MP3文件:

f = open(name, 'rb')
data = f.read(10000)

其中name是我们传给函数play_mp3的参数,即要打开的MP3文件名。接着使用文件的read函数读取10000个字节的数据,从前面的MP3 文件格式分析可以知道,MP3文件的头部长度是不确定的,所以我们不知道真正的音频帧数据从哪里开始,我们要先读取前面的一段数据,把其中的音频数据帧解析出来,然后在播放。

dm = muxer.Demuxer('mp3')
frames = dm.parse(data)
print len(frames)

首先我们创建一个MP3的Demuxer对象dm,然后调用dm的parse方法就可以从这个10000个字节的数据中解析出真正的音频帧数据,并存放在frames列表中。我们添加打印信息可以看到每次从读取文件的数据解析出的音频帧数:

F:\python\python_proj>python mp3.py dadi.mp3
2
3
2
2
3
2
3
2
3
2
3
2
2

2.我们从MP3文件中获取真正的音频帧数据后,接着要一帧一帧地进行解码操作。

            for frame in frames:
                if dec == None:
                    dec = acodec.Decoder(dm.streams[0])
                r = dec.decode(frame[1])
                if r and r.data:
                    if snd == None:
                        snd = sound.Output(r.sample_rate, r.channels, sound.AFMT_S16_LE)
                    snd.play(r.data)

首先我们生成一个解码器对象dec来解码我们的音频文件。对于一帧数据frame,从Pymedia设计和打印相关信息,我们可以看到frame[1]才是真正的音频数据,所以我们直接对frame[1]中的数据进行解码,解码以后我们就可以创建一个音频输出对象snd,然后调用音频输出对象snd的play方法就可以直接播放音乐了,该方法会通过系统调用,触发驱动的写 dsp设备节点操作,从而驱动声卡发出声音,播放音乐。当每次读取完最后一阵数据以后,要让程序延迟一会载退出,否则最后一帧数据还没来得及播放出来,程序就结束了。

    while snd.isPlaying():
        time.sleep(0.05)
《Linux三剑客》视频教程,从零开始快速掌握Linux开发常用的工具:Git、Makefile、vim、autotools、debug,免费赠送C语言视频教程,C语言项目实战:学生成绩管理系统。详情请点击淘宝链接:Linux三剑客