录制和识别来自 URL 的音乐

Record and Recognize music from URL

我在 python DeJavu 中使用开源音频指纹识别平台,它可以识别来自磁盘和麦克风的音乐。 我已经测试了从磁盘的识别,这是惊人的。 100% 准确率。

我寻求有关如何添加 class "BroadcastRecognizer" 的帮助 这将从 URL 在线流示例在线广播中识别音乐 [http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p] 因为广播流里的音乐是不断变化的,想设置为每10秒识别一次。

这是recognize.py

import dejavu.fingerprint as fingerprint
import dejavu.decoder as decoder
import numpy as np
import pyaudio
import time


class BaseRecognizer(object):

def __init__(self, dejavu):
    self.dejavu = dejavu
    self.Fs = fingerprint.DEFAULT_FS

def _recognize(self, *data):
    matches = []
    for d in data:
        matches.extend(self.dejavu.find_matches(d, Fs=self.Fs))
    return self.dejavu.align_matches(matches)

def recognize(self):
    pass  # base class does nothing


class FileRecognizer(BaseRecognizer):
def __init__(self, dejavu):
    super(FileRecognizer, self).__init__(dejavu)

def recognize_file(self, filename):
    frames, self.Fs, file_hash = decoder.read(filename, self.dejavu.limit)

    t = time.time()
    match = self._recognize(*frames)
    t = time.time() - t

    if match:
        match['match_time'] = t

    return match

def recognize(self, filename):
    return self.recognize_file(filename)


class MicrophoneRecognizer(BaseRecognizer):
default_chunksize   = 8192
default_format      = pyaudio.paInt16
default_channels    = 2
default_samplerate  = 44100

def __init__(self, dejavu):
    super(MicrophoneRecognizer, self).__init__(dejavu)
    self.audio = pyaudio.PyAudio()
    self.stream = None
    self.data = []
    self.channels = MicrophoneRecognizer.default_channels
    self.chunksize = MicrophoneRecognizer.default_chunksize
    self.samplerate = MicrophoneRecognizer.default_samplerate
    self.recorded = False

def start_recording(self, channels=default_channels,
                    samplerate=default_samplerate,
                    chunksize=default_chunksize):
    self.chunksize = chunksize
    self.channels = channels
    self.recorded = False
    self.samplerate = samplerate

    if self.stream:
        self.stream.stop_stream()
        self.stream.close()

    self.stream = self.audio.open(
        format=self.default_format,
        channels=channels,
        rate=samplerate,
        input=True,
        frames_per_buffer=chunksize,
    )

    self.data = [[] for i in range(channels)]

def process_recording(self):
    data = self.stream.read(self.chunksize)
    nums = np.fromstring(data, np.int16)
    for c in range(self.channels):
        self.data[c].extend(nums[c::self.channels])

def stop_recording(self):
    self.stream.stop_stream()
    self.stream.close()
    self.stream = None
    self.recorded = True

def recognize_recording(self):
    if not self.recorded:
        raise NoRecordingError("Recording was not complete/begun")
    return self._recognize(*self.data)

def get_recorded_time(self):
    return len(self.data[0]) / self.rate

def recognize(self, seconds=10):
    self.start_recording()
    for i in range(0, int(self.samplerate / self.chunksize
                          * seconds)):
        self.process_recording()
    self.stop_recording()
    return self.recognize_recording()


class NoRecordingError(Exception):
pass

这是dejavu.py

import os``
import sys
import json
import warnings
import argparse

from dejavu import Dejavu
from dejavu.recognize import FileRecognizer
from dejavu.recognize import MicrophoneRecognizer
from argparse import RawTextHelpFormatter

warnings.filterwarnings("ignore")

DEFAULT_CONFIG_FILE = "dejavu.cnf.SAMPLE"


def init(configpath):
""" 
Load config from a JSON file
"""
try:
    with open(configpath) as f:
        config = json.load(f)
except IOError as err:
    print("Cannot open configuration: %s. Exiting" % (str(err)))
    sys.exit(1)

# create a Dejavu instance
return Dejavu(config)


if __name__ == '__main__':
parser = argparse.ArgumentParser(
    description="Dejavu: Audio Fingerprinting library",
    formatter_class=RawTextHelpFormatter)
parser.add_argument('-c', '--config', nargs='?',
                    help='Path to configuration file\n'
                         'Usages: \n'
                         '--config /path/to/config-file\n')
parser.add_argument('-f', '--fingerprint', nargs='*',
                    help='Fingerprint files in a directory\n'
                         'Usages: \n'
                         '--fingerprint /path/to/directory extension\n'
                         '--fingerprint /path/to/directory')
parser.add_argument('-r', '--recognize', nargs=2,
                    help='Recognize what is '
                         'playing through the microphone\n'
                         'Usage: \n'
                         '--recognize mic number_of_seconds \n'
                         '--recognize file path/to/file \n')
args = parser.parse_args()

if not args.fingerprint and not args.recognize:
    parser.print_help()
    sys.exit(0)

config_file = args.config
if config_file is None:
    config_file = DEFAULT_CONFIG_FILE
    # print "Using default config file: %s" % (config_file)

djv = init(config_file)
if args.fingerprint:
    # Fingerprint all files in a directory
    if len(args.fingerprint) == 2:
        directory = args.fingerprint[0]
        extension = args.fingerprint[1]
        print("Fingerprinting all .%s files in the %s directory"
              % (extension, directory))
        djv.fingerprint_directory(directory, ["." + extension], 4)

    elif len(args.fingerprint) == 1:
        filepath = args.fingerprint[0]
        if os.path.isdir(filepath):
            print("Please specify an extension if you'd like to fingerprint a directory!")
            sys.exit(1)
        djv.fingerprint_file(filepath)

elif args.recognize:
    # Recognize audio source
    song = None
    source = args.recognize[0]
    opt_arg = args.recognize[1]

    if source in ('mic', 'microphone'):
        song = djv.recognize(MicrophoneRecognizer, seconds=opt_arg)
    elif source == 'file':
        song = djv.recognize(FileRecognizer, opt_arg)
    print(song)

sys.exit(0)

我仍然认为您需要一个离散的 "piece" 音频,因此您需要一个开头和一个结尾。
对于它的价值,从这样的东西开始,它记录了 10 秒的音频,然后你可以根据你的指纹记录进行测试。
注意:这是针对 python 2 的,因此您必须在 python 3

上将其编辑为 运行
import time, sys
import urllib2
url = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p"
print ("Connecting to "+url)
response = urllib2.urlopen(url, timeout=10.0)
fname = "Sample"+str(time.clock())[2:]+".wav"
f = open(fname, 'wb')
block_size = 1024
print ("Recording roughly 10 seconds of audio Now - Please wait")
limit = 10
start = time.time()
while time.time() - start < limit:
    try:
        audio = response.read(block_size)
        if not audio:
            break
        f.write(audio)
        sys.stdout.write('.')
        sys.stdout.flush()
    except Exception as e:
        print ("Error "+str(e))
f.close()
sys.stdout.flush()
print("")
print ("10 seconds from "+url+" have been recorded in "+fname)

#
# here run the finger print test to identify the audio recorded
# using the sample you have downloaded in the file "fname"
#