Work with Audio
Audio files are stored as Blobs in ApertureDB. The query language lets you add, find, update, and delete audio blobs with rich metadata — dish name, contributor, cuisine — so you can retrieve exactly the clips you need.
Connect to ApertureDB
Option A: ApertureDB Cloud (recommended)
Sign up for a free 30-day trial. Get your key from Connect > Generate API Key, add it to a .env file in this directory:
APERTUREDB_KEY=your_key_here
Option B: Community Edition (local Docker)
Run this in a terminal before starting the notebook:
docker run -d --name aperturedb \
-p 55555:55555 -e ADB_MASTER_KEY=admin -e ADB_FORCE_SSL=false \
aperturedata/aperturedb-community
See client configuration options for all connection methods and server setup options for deployment choices.
%pip install --upgrade --quiet aperturedb python-dotenv
# Option A: ApertureDB Cloud
from dotenv import load_dotenv
load_dotenv() # loads APERTUREDB_KEY from .env into the environment
True
# Option B: Community Edition (local Docker)
# !adb config create localdb --active \
# --host localhost --port 55555 \
# --username admin --password admin \
# --no-use-ssl --no-interactive
from aperturedb.CommonLibrary import create_connector
client = create_connector()
response, _ = client.query([{"GetStatus": {}}])
client.print_last_response()
[
{
"GetStatus": {
"info": "OK",
"status": 0,
"system": "ApertureDB",
"version": "0.19.6"
}
}
]
Generate a Sample Audio Clip
For this example we generate a short WAV file — a cooking timer beep — using Python's built-in wave module. In practice, replace this with any .wav, .mp3, or other audio file from your recipe recordings.
import wave, struct, math, os
os.makedirs("data", exist_ok=True)
sample_rate = 44100
duration = 2 # seconds
frequency = 880 # Hz — a short timer beep
# Apply a short fade-out to avoid clipping
samples = []
total = sample_rate * duration
for t in range(total):
fade = max(0.0, 1.0 - t / total)
samples.append(int(32767 * fade * math.sin(2 * math.pi * frequency * t / sample_rate)))
with wave.open("data/cooking_timer.wav", "w") as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(sample_rate)
f.writeframes(struct.pack("<" + "h" * len(samples), *samples))
print(f"Generated data/cooking_timer.wav ({os.path.getsize('data/cooking_timer.wav')} bytes)")
Generated data/cooking_timer.wav (176444 bytes)
Preview the audio clip before storing it:
from IPython.display import Audio
Audio("data/cooking_timer.wav")
Add an Audio Blob to ApertureDB
Use AddBlob to store the audio binary alongside metadata. Setting type: audio makes it easy to filter later.
For bulk additions, use the Python SDK loaders.
query = [{
"AddBlob": {
"properties": {
"document_type": "wav",
"type": "audio",
"format": "wav",
"name": "cooking_timer",
"dish_name": "Baked Potato",
"cuisine": "American",
"contributor": "Gavin",
"duration_s": 2,
},
"if_not_found": {"name": ["==", "cooking_timer"]},
}
}]
with open("data/cooking_timer.wav", "rb") as f:
audio_bytes = f.read()
response, _ = client.query(query, [audio_bytes])
client.print_last_response()
[
{
"AddBlob": {
"status": 0
}
}
]
Find Audio Blobs by Metadata
Use FindBlob with constraints to retrieve audio clips. Set blobs: true to get the binary back.
query = [{
"FindBlob": {
"constraints": {
"type": ["==", "audio"],
"cuisine": ["==", "American"],
},
"blobs": True,
"results": {"all_properties": True},
}
}]
response, blobs = client.query(query)
client.print_last_response()
[
{
"FindBlob": {
"blobs_start": 0,
"entities": [
{
"_blob_index": 0,
"_uniqueid": "7.3.483380",
"contributor": "Gavin",
"cuisine": "American",
"dish_name": "Baked Potato",
"document_type": "wav",
"duration_s": 2,
"format": "wav",
"name": "cooking_timer",
"type": "audio"
}
],
"returned": 1,
"status": 0
}
}
]
Play back the retrieved audio:
from IPython.display import Audio
if blobs:
display(Audio(blobs[0]))
Update Audio Blob Metadata
Use UpdateBlob to add or change properties on existing blobs.
query = [{
"UpdateBlob": {
"constraints": {"name": ["==", "cooking_timer"]},
"properties": {"verified": True},
}
}]
response, _ = client.query(query)
client.print_last_response()
[
{
"UpdateBlob": {
"count": 1,
"status": 0
}
}
]
Delete the Audio Blob
query = [{
"DeleteBlob": {
"constraints": {"name": ["==", "cooking_timer"]},
}
}]
response, _ = client.query(query)
client.print_last_response()
[
{
"DeleteBlob": {
"count": 1,
"status": 0
}
}
]
What's Next?
- Work with Blobs — text files, PDFs, and other binary formats
- Work with Videos — add cooking video clips
- Bulk load — ingest many audio files at once with ParallelLoader
- Add connections — link audio clips to dish images or recipes