Skip to content

Commit 7282b82

Browse files
committed
0.11
--url and fastapi backend
1 parent 9220c82 commit 7282b82

9 files changed

+84
-16
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ __pycache__/
88
csv_dup.py
99
proxy.py
1010
*.opus
11+
.pypirc
1112

1213
# C extensions
1314
*.so

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ pyzam --microphone
4444

4545
# Listen to audio files
4646
pyzam --input audio_file.mp3
47+
48+
# Listen to audio via URL
49+
pyzam --url "https://archive.org/download/09-hold-me-in-your-arms/02%20-%20Never%20Gonna%20Give%20You%20Up.mp3"
4750
```
4851

4952
```bash
@@ -62,6 +65,7 @@ See `pyzam --help` for more options.
6265
| --input | Detects from the given audio input file.
6366
| --microphone, -m | Listens to the microphone of your device.
6467
| --speaker, -s | Listens to the speaker of your device (default).
68+
| --url, -u | Detects from the given URL to an audio file.
6569
| --help, -h | Show usage & options and exit.
6670
| --duration, -d | Length of microphone or speaker recording. Max = 12 seconds.
6771
| --loop, -l | Loop the recognition process indefinitely.

fastapi/main.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from fastapi import FastAPI, HTTPException
2+
import subprocess
3+
4+
app = FastAPI()
5+
6+
@app.get("/identify/")
7+
async def identify_song(url: str):
8+
command = [
9+
"pyzam",
10+
"--url", str(url),
11+
"--json" # Use JSON mode
12+
]
13+
14+
try:
15+
result = subprocess.run(command, capture_output=True, text=True, check=True)
16+
return "\n".join(result.stdout.splitlines()[1:]) # Return everything after the first line
17+
except subprocess.CalledProcessError as e:
18+
raise HTTPException(status_code=500, detail=f"Error: {e.stderr}")

pyzam/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.1"
1+
__version__ = "0.11"

pyzam/__main__.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#! /usr/bin/env python3
22

33
"""
4-
Pyzam 0.10
5-
A CLI music recognition tool for audio and mixtapes using Python.
4+
Pyzam 0.11
5+
A CLI music recognition tool for audio and mixtapes.
66
"""
77

88
import argparse
@@ -15,8 +15,6 @@
1515
import sys
1616
import tempfile
1717

18-
import logging
19-
2018

2119
def _parser() -> argparse.ArgumentParser:
2220
parser = argparse.ArgumentParser(
@@ -40,6 +38,11 @@ def _parser() -> argparse.ArgumentParser:
4038
action="store_true",
4139
help="record audio from speaker (default)",
4240
)
41+
input_group.add_argument(
42+
"-u",
43+
"--url",
44+
help="Detect from an audio URL",
45+
)
4346

4447
parser.add_argument(
4548
"-d", "--duration", type=int, default=5, help="audio recording duration (s)"
@@ -78,6 +81,10 @@ def get_input_file(args, temp_dir) -> Path:
7881
return record.speaker(
7982
filename=f"{temp_dir}/pyzam_speaker.wav", seconds=args.duration
8083
)
84+
elif args.url:
85+
return record.url(url=args.url,
86+
filename=f"{temp_dir}/pyzam_url.wav"
87+
)
8188
else:
8289
return args.input
8390

@@ -104,12 +111,15 @@ def main() -> None:
104111
parser = _parser()
105112
args = parser.parse_args()
106113

107-
# Check if --input and --loop are used together
114+
# Check if --input or --url and --loop are used together
108115
if args.input and args.loop:
109116
parser.error("--loop is only allowed with --microphone or --speaker")
117+
if args.url and args.loop:
118+
parser.error("--loop is only allowed with --microphone or --speaker")
119+
110120
# Check if --mixtape and (--microphone or --speaker) are used together
111121
if args.mixtape and (args.microphone or args.speaker):
112-
parser.error("--mixtape is only allowed with --input")
122+
parser.error("--mixtape is only allowed with --input or --url")
113123

114124
temp_dir = tempfile.gettempdir()
115125

pyzam/identify.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ async def identify_audio(
7777

7878
if json:
7979
print(out)
80-
return
80+
return out
8181

8282
track_info = extract_track_info(out)
8383
print_track_info(track_info)

pyzam/record.py

+32-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
import requests
12
import soundcard as sc
23
import soundfile as sf
4+
import io
35

46

57
def speaker(filename: str, seconds):
68
"""
79
Records the device's speaker.
810
9-
:param filename: Name of audio file written.
11+
:param filename: Name and directory of the audio file written.
1012
:param seconds: Duration to record (seconds).
1113
"""
1214
with sc.get_microphone(
@@ -23,7 +25,7 @@ def microphone(filename: str, seconds):
2325
"""
2426
Records the device's device.
2527
26-
:param filename: Name of audio file written.
28+
:param filename: Name and directory of the audio file written.
2729
:param seconds: Duration to record (seconds).
2830
"""
2931
with sc.get_microphone(
@@ -33,3 +35,31 @@ def microphone(filename: str, seconds):
3335
data = mic.record(numframes=44100 * seconds)
3436
sf.write(file=filename, data=data, samplerate=44100)
3537
return filename
38+
39+
40+
def url(url: str, filename: str):
41+
"""
42+
Downloads audio from the provided URL.
43+
44+
:param url: URL of the audio file.
45+
:param filename: Name and directory of the audio file written.
46+
:param seconds: Duration to record (seconds).
47+
"""
48+
print(f"Downloading audio from URL...")
49+
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246'}
50+
51+
try:
52+
response = requests.get(url, headers=headers)
53+
response.raise_for_status() # Raises an HTTPError if code is 4XX/5XX
54+
55+
except requests.exceptions.HTTPError as http_err:
56+
print(f'HTTP error occurred: {http_err}')
57+
return None
58+
except Exception as err:
59+
print(f'An error occurred: {err}')
60+
return None
61+
62+
# Ensure the response content is in a suitable format for soundfile
63+
data, samplerate = sf.read(io.BytesIO(response.content))
64+
sf.write(file=filename, data=data, samplerate=samplerate)
65+
return filename

requirements.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
asyncio==3.4.3
2-
rich==13.7.1
2+
fastapi==0.111.0
3+
rich==13.8
34
soundfile==0.12.1
4-
shazamio==0.5.1
5-
SoundCard==0.4.3
6-
#tk for live-recog-dev folder
5+
shazamio==0.6
6+
SoundCard==0.4.3

setup.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
setuptools.setup(
77
name="pyzam",
8-
version="0.10",
8+
version="0.11",
99
entry_points={"console_scripts": ["pyzam = pyzam.__main__:main"]},
1010
author="lukafilipxvic",
11-
description="A CLI music recognition tool for audio and mixtapes using Python.",
11+
description="A CLI music recognition tool for audio and mixtapes.",
1212
long_description=long_description,
1313
long_description_content_type="text/markdown",
1414
url="https://github.com/lukafilipxvic/Pyzam",
@@ -21,4 +21,9 @@
2121
],
2222
packages=setuptools.find_packages(),
2323
python_requires=">=3.9",
24+
license="MIT",
25+
classifiers=[
26+
"Programming Language :: Python :: 3",
27+
"License :: OSI Approved :: MIT License",
28+
]
2429
)

0 commit comments

Comments
 (0)