Python通过90行代码搭建一个音乐搜索工具

下面小编把具体实现代码给大家分享如下:

之前一段时间读到了这篇博客,其中描述了作者如何用java实现国外著名音乐搜索工具shazam的基本功能。其中所提到的文章又将我引向了关于shazam的一篇论文及另外一篇博客。读完之后发现其中的原理并不十分复杂,但是方法对噪音的健壮性却非常好,出于好奇决定自己用python自己实现了一个简单的音乐搜索工具—— Song Finder, 它的核心功能被封装在SFEngine 中,第三方依赖方面只使用到了 scipy。

工具demo
这个demo在ipython下展示工具的使用,本项目名称为Song Finder,我把索引、搜索的功能全部封装在Song Finder中的SFEngine中。首先是简单的准备工作:

代码如下:

In [1]: from SFEngine import *

In [2]: engine = SFEngine()

在这之后我们对现有歌曲进行索引,我在original目录下准备了几十首歌曲(.wav文件)作为曲库:

代码如下:

In [3]: engine.index('original') # 索引该目录下的所有歌曲

在完成索引之后我们向Song Finder提交一段有背景噪音的歌曲录音进行搜索。对于这段《枫》在1分15秒左右的录音:

工具的返回结果是:

代码如下:

In [4]: engine.search('record/record0.wav')
original/周杰伦-枫 73
original/周杰伦-枫 31
original/周杰伦-枫 10
original/周杰伦-枫 28
original/我要快樂 - 張惠妹 28

其中展示的分别是歌曲名称及片段在歌曲中出现的位置(以秒计),可以看到工具正确找回了歌曲的曲名,也找到了其在歌曲中的正确位置。

而对于这段《童话》在1分05秒左右的背景噪音更加嘈杂的录音:

工具的返回结果是:

代码如下:

In [5]: engine.search('record/record8.wav')
original/光良 - 童话 67
original/光良 - 童话 39
original/光良 - 童话 33
original/光良 - 童话 135
original/光良 - 童话 69

可以看到尽管噪音非常嘈杂,但是工具仍然能成功识别所对应的歌曲并对应到歌曲的正确位置,说明工具在噪音较大的环境下有良好的健壮性!

项目主页: Github

Song Finder原理
给定曲库对一个录音片段进行检索是一个不折不扣的搜索问题,但是对音频的搜索并不像对文档、数据的搜索那么直接。为了完成对音乐的搜索,工具需要完成下列3个任务:

对曲库中的所有歌曲抽取特征
以相同的方式对录音片段提取特征
根据录音片段的特征对曲库进行搜索,返回最相似的歌曲及其在歌曲中的位置
特征提取?离散傅立叶变换!
为了对音乐(音频)提取特征,一个很直接的想法是得到音乐的音高的信息,而音高在物理上对应的则又是波的频率信息。为了获取这类信息,一个非常直接的额做法是使用离散傅叶变化对声音进行分析,即使用一个滑动窗口对声音进行采样,对窗口内的数据进行离散傅立叶变化,将时间域上的信息变换为频率域上的信息,使用scipy的接口可以很轻松的完成。在这之后我们将频率分段,提取每频率中振幅最大的频率:

代码如下:

def extract_feature(self, scaled, start, interval):
    end = start + interval
    dst = fft(scaled[start: end])
    length = len(dst)/2 
    normalized = abs(dst[:(length-1)])
    feature = [ normalized[:50].argmax(), \
                50 +  normalized[50:100].argmax(), \
                100 + normalized[100:200].argmax(), \
                200 + normalized[200:300].argmax(), \
                300 + normalized[300:400].argmax(), \
                400 + normalized[400:].argmax()]
    return feature

这样,对于一个滑动窗口,我提取到了6个频率作为其特征。对于整段音频,我们重复调用这个函数进行特征抽取:

def sample(self, filename, start_second, duration = 5, callback = None):

 start = start_second * 44100
 if duration == 0:
  end = 1e15
 else:
  end = start + 44100 * duration
 interval = 8192
 scaled = self.read_and_scale(filename)
 length = scaled.size
 while start < min(length, end):
  feature = self.extract_feature(scaled, start, interval)
  if callback != None:
   callback(filename, start, feature)
  start += interval

其中44100为音频文件自身的采样频率,8192是我设定的取样窗口(对,这样hardcode是很不对的),callback是一个传入的函数,需要这个参数是因为在不同场景下对于所得到的特征会有不同的后续操作。

匹配曲库
在得到歌曲、录音的大量特征后,如何进行高效搜索是一个问题。一个有效的做法是建立一个特殊的哈希表,其中的key是频率,其对应的value是一系列(曲名,时间)的tuple,其记录的是某一歌曲在某一时间出现了某一特征频率,但是以频率为key而非以曲名或时间为key。

表格。。

这样做的好处是,当在录音中提取到某一个特征频率时,我们可以从这个哈希表中找出与该特征频率相关的歌曲及时间!

当然有了这个哈希表还不够用,我们不可能把所有与特征频率相关的歌曲都抽出来,看看谁命中的次数多,因为这样会完全无视歌曲的时序信息,并引入一些错误的匹配。

我们的做法是,对于录音中在t时间点的一个特征频率f,从曲库找出所有与f相关的(曲名,时间)tuple,例如我们得到了

代码如下:

[(s1, t1), (s2, t2), (s3, t3)]

我们使用时间进行对齐,得到这个列表

代码如下:

[(s1, t1-t), (s2, t2-t), (s3, t3-t)]

记为

代码如下:

[(s1, t1`), (s2, t2`), (s3, t3`)]

我们对所有时间点的所有特征频率均做上述操作,得到了一个大列表:

代码如下:

[(s1, t1`), (s2, t2`), (s3, t3`), ..., (sn, tn`)]

对这个列表进行计数,可以看到哪首歌曲的哪个时间点命中的次数最多,并将命中次数最多的(曲名,时间)对返回给用户。

不足
这个小工具是一个几个小时写成的hack,有许都地方需要改进,例如:

目前只支持了wav格式的曲库及录音
所有数据都放在内存中,曲库体积增大时需要引入更好的后端存储
索引应该并行化,匹配也应该并行化,匹配的模型其实是典型的map-reduce。

以上就是Python通过90行代码搭建音乐搜索工具,希望大家喜欢。

(0)

相关推荐

  • python基于urllib实现按照百度音乐分类下载mp3的方法

    本文实例讲述了python基于urllib实现按照百度音乐分类下载mp3的方法.分享给大家供大家参考.具体实现方法如下: #!/usr/bin/env python #-*- coding: utf-8 -*- import urllib import re baseurl = "http://music.baidu.com" url = "http://music.baidu.com/search/tag?key=经典流行" html = urllib.urlop

  • 听歌识曲--用python实现一个音乐检索器的功能

    听歌识曲,顾名思义,用设备"听"歌曲,然后它要告诉你这是首什么歌.而且十之八九它还得把这首歌给你播放出来.这样的功能在QQ音乐等应用上早就出现了.我们今天来自己动手做一个自己的听歌识曲 我们设计的总体流程图很简单: ----- 录音部分 ----- 我们要想"听",就必须先有录音的过程.在我们的实验中,我们的曲库也要用我们的录音代码来进行录音,然后提取特征存进数据库.我们用下面这样的思路来录音 # coding=utf8 import wave import pya

  • Python爬取qq music中的音乐url及批量下载

    前言 qq music上的音乐还是不少的,有些时候想要下载好听的音乐,但有每次在网页下载都是烦人的登录什么的.于是,来了个qqmusic的爬虫.至少我觉得for循环爬虫,最核心的应该就是找到待爬元素所在url吧.下面开始找吧(讲的不对不要笑我) 实现如下 #寻找url: 这个url可不想其他的网站那么好找.把我给累得不轻,关键是数据多,从那么多数据里面挑出有用的数据,最后组合为music真正的music.昨天做的时候整理的几个中间url: #url1:https://c.y.qq.com/sos

  • Python爬取网易云音乐上评论火爆的歌曲

    前言 网易云音乐这款音乐APP本人比较喜欢,用户量也比较大,而网易云音乐之所以用户众多和它的歌曲评论功能密不可分,很多歌曲的评论非常有意思,其中也不乏很多感人的评论.但是,网易云音乐并没有提供热评排行榜和按评论排序的功能,没关系,本文就使用爬虫给大家爬一爬网易云音乐上那些热评的歌曲. 结果 对过程没有兴趣的童鞋直接看这里啦. 评论数大于五万的歌曲排行榜 首先恭喜一下我最喜欢的歌手(之一)周杰伦的<晴天>成为网易云音乐第一首评论数过百万的歌曲! 通过结果发现目前评论数过十万的歌曲正好十首,通过这

  • 使用Python实现下载网易云音乐的高清MV

    Python下载网易云音乐的高清MV,没有从首页进去解析,直接循环了.... downPage1.py 复制代码 代码如下: #coding=utf-8 import urllib import re import os def getHtml(url):     page = urllib.urlopen(url)     html = page.read()     return html def getVideo(html):     reg = r'hurl=(.+?\.jpg)'   

  • Python实现提取谷歌音乐搜索结果的方法

    本文实例讲述了Python实现提取谷歌音乐搜索结果的方法.分享给大家供大家参考.具体如下: Python的简单脚本,用于提取谷歌音乐搜索页面中的歌曲信息,包括歌曲名,作者,专辑名,现在链接等,最多只提取10页结果. #! /usr/bin/env python #coding=utf-8 ''' Created on 2011-8-19 @author: yaoboyuan ''' from urllib import request,parse import re,sys def extrac

  • python3音乐播放器简单实现代码

    本文实例为大家分享了python3音乐播放器的关键代码,供大家参考,具体内容如下 from tkinter import * from traceback import * from win32com.client import Dispatch import time,eyed3,threading name = [] def openfile(index = [1]): global total,name filenames = filedialog.askopenfilenames(tit

  • python中使用百度音乐搜索的api下载指定歌曲的lrc歌词

    这次这个真的是干货哦,昨晚弄了半晚上,,,,从8点吃完饭就开始写,一直到了快12点才弄好,,,新手,伤不起呀.... 先简单的说下吧,百度提供了一个音乐搜索的api,你想百度请求类似于 http://box.zhangmen.baidu.com/x?op=12&count=1&title=最佳损友$$陈奕迅$$$$ 的地址,百度会给你返回一段xml,如下所示 This XML file does not appear to have any style information associ

  • Python多线程结合队列下载百度音乐的方法

    本文实例讲述了Python多线程结合队列下载百度音乐的方法.分享给大家供大家参考.具体如下: 一直想做个下载音乐的脚本,后来决定就拿百度音乐开刀,经过多次分析,终于制作了一个下载百度音乐的脚本,目前只默认下载第一页,童鞋们可以自由拓展. 适用Windows和Linux平台.依赖BeautifulSoup这个库,主要对HTML进行解析 #!/usr/bin/python # -*- coding: utf-8 -*- ''' 百度中批量下载某歌手的歌(目前只下载第一页,可以自行拓展) @autho

  • Python通过90行代码搭建一个音乐搜索工具

    下面小编把具体实现代码给大家分享如下: 之前一段时间读到了这篇博客,其中描述了作者如何用java实现国外著名音乐搜索工具shazam的基本功能.其中所提到的文章又将我引向了关于shazam的一篇论文及另外一篇博客.读完之后发现其中的原理并不十分复杂,但是方法对噪音的健壮性却非常好,出于好奇决定自己用python自己实现了一个简单的音乐搜索工具-- Song Finder, 它的核心功能被封装在SFEngine 中,第三方依赖方面只使用到了 scipy. 工具demo 这个demo在ipython

  • Python用5行代码写一个自定义简单二维码

    python的优越之处就在于他可以直接调用已经封装好的包 首先,下载pillow和qrcode包  终端下键入一下命令: pip3 install pillow #python2 用pip install pillow pip3 install qrcode 实现代码: import qrcode # 定义一个类名 def qrcodeWithUrl(url): img = qrcode.make(url) # 生成一个二维码 savePath = "baidu.png" # 存储二维

  • python实战之90行代码写个猜数字游戏

    一.导入库 import random import time 二.注册用户 我们用变量与input实现 name = str(input('请输入用户名:')) print('欢迎您,'+name) 三.注册年龄 这里我们得用except制作乱输文本就游戏结束的程序 乱输文本就结束 try: age = int(input('请输入年龄:')) except ValueError: print('非法输入') age = 30000 顺便把年龄设为30000[滑稽] 再根据年龄大小分配金币 四

  • Python+tkinter使用80行代码实现一个计算器实例

    本文主要探索的是使用Python+tkinter编程实现一个简单的计算器代码示例,具体如下. 闲话不说,直奔主题.建议大家跟着敲一遍代码,体会一下代码复用.字符串方法的运用和动态创建组件的妙处,然后在这个框架的基础上进行补充和发挥. 选择任何一款Python开发环境,创建一个程序文件,命名为tkinter_Calculator.pyw,然后编写下面的代码: 1)导入标准库re和tkinter,创建并简单设置应用主程序,在窗口顶部放置一个只读的文本框用来显示信息. 2)编写计算器上各种按钮的通用处

  • Python实现3行代码解简单的一元一次方程

    本文所述实例为Python用3行代码实现解一元一次方程,代码简洁高效,具体用法如下: >>> solve("x - 2*x + 5*x - 46*(235-24) = x + 2") 3236.0 功能代码如下: def solve(eq,var='x'): eq1 = eq.replace("=","-(")+")" c = eval(eq1,{var:1j}) return -c.real/c.imag

  • Python用5行代码实现批量抠图的示例代码

    前言 对于会PhotoShop的人来说,抠图是非常简单的操作了,有时候几秒钟就能扣好一张图.不过一些比较复杂的图,有时候还是要画点时间的,今天就给大家带了一个非常快速简单的办法,用Python来批量抠取人像. 效果展示 开始吧,我也不看好什么自动抠图,总觉得不够精确,抠不出满意的图.下面我就直接展示一下效果图吧.我们先看看原图 这张图片背景未纯色,我们平时用PhotoShop抠起来也比较简单,对我们计算机来说也不是什么难题,下面是效果图: 因为本身是PNG图片,而且原图是白色背景,所以看不出什么

  • python用700行代码实现http客户端

    本文用python在TCP的基础上实现一个HTTP客户端, 该客户端能够复用TCP连接, 使用HTTP1.1协议. 一. 创建HTTP请求 HTTP是基于TCP连接的, 它的请求报文格式如下: 因此, 我们只需要创建一个到服务器的TCP连接, 然后按照上面的格式写好报文并发给服务器, 就实现了一个HTTP请求. 1. HTTPConnection类 基于以上的分析, 我们首先定义一个HTTPConnection类来管理连接和请求内容: class HTTPConnection: default_

  • Python使用5行代码批量做小姐姐的素描图

    目录 1. 流程分析 2. 具体实现 3. 百度图片爬虫+生成素描图 我给大家带来的是 50行代码,生成一张素描图.让自己也是一个素描"大师".那废话不多说,我们直接先来看看效果吧. 上图的右边就是我们的效果,那具体有哪些步骤呢? 1. 流程分析 对于上面的流程来说是非常简单的,接下来我们来看看具体的实现. 2. 具体实现 安装所需要的库: pip install opencv-python 导入所需要的库: import cv2 编写主体代码也是非常的简单的,代码如下: import

  • Python用20行代码实现完整邮件功能

    目录 Python实现完整邮件 一.邮箱端设置 1.首先登录网页版126邮箱 2.打开 设置-POP3/SMTP/IMAP配置界面 3.新增一个授权码 二.python发送邮件 1.安装邮件模块 2.调用模块 3.设置邮件内容 4.添加附件 三.python读取邮件 Python实现完整邮件 先上效果: 一.邮箱端设置 首先,要对邮件进行一下设置,在邮箱端获取一个授权码. 1.首先登录网页版126邮箱 2.打开 设置-POP3/SMTP/IMAP配置界面 3.新增一个授权码 二.python发送

  • 如何用Python中19行代码把照片写入到Excel中

    目录 1.前言 2.代码实战 2.1思路 2.2文件准备 2.3实战 2.4色值转换 2.5图片转换 2.6代码整合 2.7运行结果 3.总结 1.前言 这里说的,不是截取一张图片,粘贴到excel:而是通过像素写入到excel中,下面来看看具体的实现过程吧 2.代码实战 2.1 思路 我们今天要分享的,是把图片写入到excel中, 我们来捋一下思路: 准备源图片,目标excel: 通过Pillow 来读图片的取像素(RGB): 通过openpyxl 向excel cell内填充十六进制色值:

随机推荐