-
Notifications
You must be signed in to change notification settings - Fork 12
Configuration
This guide covers all configuration options for Muze, including API keys, server settings, and customization options.
Location: algorithmia.py line 17
Current (Insecure):
client = Algorithmia.client('api-key')Recommended (Secure):
import os
from dotenv import load_dotenv
load_dotenv()
client = Algorithmia.client(os.getenv('ALGORITHMIA_API_KEY'))Setup:
- Create
.envfile in project root:
ALGORITHMIA_API_KEY=simYOUR_ACTUAL_KEY_HERE- Install python-dotenv:
pip install python-dotenv- Add
.envto.gitignore:
echo ".env" >> .gitignoreGet API Key:
- Visit algorithmia.com
- Sign up or log in
- Navigate to Profile → Credentials
- Copy API key (starts with "sim")
Location: app.py line 12
Current (Insecure):
app.secret_key = "bacon"Recommended (Secure):
import os
from dotenv import load_dotenv
load_dotenv()
app.secret_key = os.getenv('FLASK_SECRET_KEY', 'fallback-secret-key')Generate Secure Key:
import secrets
print(secrets.token_hex(32))Add to .env:
FLASK_SECRET_KEY=your_generated_key_hereLocation: app.py line 37-38
Current:
if __name__ == '__main__':
app.run(debug=True)Configuration Options:
app.run(
host='0.0.0.0', # Listen on all interfaces
port=5000, # Port number
debug=True, # Debug mode (disable in production)
threaded=True, # Handle multiple requests
ssl_context=None # SSL configuration
)Recommended Approach:
import os
from dotenv import load_dotenv
load_dotenv()
if __name__ == '__main__':
app.run(
host=os.getenv('FLASK_HOST', '127.0.0.1'),
port=int(os.getenv('FLASK_PORT', 5000)),
debug=os.getenv('FLASK_DEBUG', 'True') == 'True'
).env Configuration:
FLASK_HOST=0.0.0.0
FLASK_PORT=5000
FLASK_DEBUG=True
FLASK_ENV=developmentInstall:
pip install gunicornRun:
gunicorn -w 4 -b 0.0.0.0:5000 app:appConfiguration File (gunicorn.conf.py):
bind = "0.0.0.0:5000"
workers = 4
worker_class = "sync"
timeout = 120
keepalive = 5
errorlog = "logs/error.log"
accesslog = "logs/access.log"
loglevel = "info"Run with Config:
gunicorn -c gunicorn.conf.py app:appInstall:
pip install waitressRun:
waitress-serve --port=5000 --threads=4 app:appPython Script (run_production.py):
from waitress import serve
from app import app
serve(app, host='0.0.0.0', port=5000, threads=4)Location: algorithmia.py lines 46-54
Current Configuration:
songlist = {
1: [1, 170],
2: [171, 334],
3: [335, 549],
4: [550, 740],
5: [741, 903]
}Customization: Adjust ranges based on your music library
Location: algorithmia.py lines 47-54
Anger/Fear:
cluster_def = [[5, 2], [3, 7], [2, 12]] # 21 songsSad:
cluster_def = [[3, 4], [4, 4], [2, 13]] # 21 songsNeutral/Disgust/Surprise:
cluster_def = [[3, 2], [4, 5], [2, 7], [1, 5]] # 19 songsHappy:
cluster_def = [[2, 10], [4, 5], [1, 6]] # 21 songsCustomization Example:
# More energetic happy playlist
if current == "Happy":
cluster_def = [[1, 15], [2, 5], [4, 1]] # 21 songs, more from cluster 1Location: algorithmia.py line 34
Current:
emotion_color_dict = {
'Neutral': 11,
'Sad': 31,
'Disgust': 51,
'Fear': 61,
'Surprise': 41,
'Happy': 21,
'Angry': 1
}Color Scheme (in get_emotion_grid()):
cmap = colors.ListedColormap([
'red', # 0-10: Angry
'blue', # 10-20: Neutral
'yellow', # 20-30: Happy
'green', # 30-40: Sad
'cyan', # 40-50: Surprise
'magenta', # 50-60: Disgust
'black', # 60-70: Fear
'white' # 80+: No data
])Customization: Change colors to match your preference
Location: templates/musi.html
Initial Snapshot Delay:
// Line 123
setTimeout(snapshot, 5000); // 5 secondsRecapture Interval:
// Line 112
if (i == 20) { // After 20 songs
setTimeout(snapshot, 5000);
}Customization:
// Faster initial capture
setTimeout(snapshot, 2000); // 2 seconds
// More frequent recapture
if (i == 10) { // After 10 songs
setTimeout(snapshot, 3000);
}Location: templates/musi.html line 28
Current:
<video width=200 height=200 id="video" controls autoplay></video>Customization:
<!-- Larger preview -->
<video width=400 height=400 id="video" controls autoplay></video>
<!-- Hide preview -->
<video hidden width=200 height=200 id="video" autoplay></video>Location: templates/musi.html line 23
Current:
<canvas hidden id="myCanvas" width="400" height="350"></canvas>Customization:
<!-- Higher resolution (better quality, larger file) -->
<canvas hidden id="myCanvas" width="640" height="480"></canvas>
<!-- Lower resolution (faster processing, smaller file) -->
<canvas hidden id="myCanvas" width="320" height="240"></canvas>Location: app.py line 24
Current:
image_PIL.save("snapshots/pic.png", mode='RGB')Customization:
import os
SNAPSHOT_DIR = os.getenv('SNAPSHOT_DIR', 'snapshots')
SNAPSHOT_FILE = os.path.join(SNAPSHOT_DIR, 'pic.png')
# Ensure directory exists
os.makedirs(SNAPSHOT_DIR, exist_ok=True)
image_PIL.save(SNAPSHOT_FILE, mode='RGB')Location: templates/musi.html line 116
Current:
$('#aud').attr('src', '/static/music/' + str);Customization:
var MUSIC_BASE_URL = '/static/music/';
$('#aud').attr('src', MUSIC_BASE_URL + str);Location: algorithmia.py line 44
Current:
with open("test.txt", "rb") as fp:
songnames = pickle.load(fp, encoding='latin1')Customization:
import os
SONG_DB_PATH = os.getenv('SONG_DB_PATH', 'test.txt')
with open(SONG_DB_PATH, "rb") as fp:
songnames = pickle.load(fp, encoding='latin1')Add to app.py:
import logging
from logging.handlers import RotatingFileHandler
# Configure logging
if not app.debug:
file_handler = RotatingFileHandler(
'logs/muze.log',
maxBytes=10240000,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Muze startup')Create Logs Directory:
mkdir logsInstall:
pip install flask-corsAdd to app.py:
from flask_cors import CORS
app = flask.Flask(__name__)
CORS(app) # Enable CORS for all routesRestricted CORS:
CORS(app, resources={
r"/hook": {"origins": "http://localhost:3000"},
r"/graph": {"origins": "http://localhost:3000"}
})Add to app.py:
@app.after_request
def set_security_headers(response):
response.headers['Content-Security-Policy'] = (
"default-src 'self'; "
"media-src 'self' blob:; "
"script-src 'self' 'unsafe-inline'; "
"style-src 'self' 'unsafe-inline';"
)
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-XSS-Protection'] = '1; mode=block'
return responseInstall:
pip install flask-limiterAdd to app.py:
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/hook', methods=['POST'])
@limiter.limit("10 per minute")
def get_image():
# ... existing code# Algorithmia Configuration
ALGORITHMIA_API_KEY=simYOUR_KEY_HERE
# Flask Configuration
FLASK_SECRET_KEY=your_secret_key_here
FLASK_ENV=development
FLASK_DEBUG=True
FLASK_HOST=127.0.0.1
FLASK_PORT=5000
# File Paths
SNAPSHOT_DIR=snapshots
SONG_DB_PATH=test.txt
MUSIC_DIR=static/music
# Logging
LOG_LEVEL=INFO
LOG_FILE=logs/muze.log
# Security
ENABLE_CORS=False
RATE_LIMIT_ENABLED=TrueAdd to app.py:
import os
import sys
def validate_config():
"""Validate required configuration before starting"""
errors = []
# Check API key
if not os.getenv('ALGORITHMIA_API_KEY'):
errors.append("ALGORITHMIA_API_KEY not set")
# Check required directories
if not os.path.exists('snapshots'):
os.makedirs('snapshots')
if not os.path.exists('static/music'):
errors.append("Music directory not found")
# Check song database
if not os.path.exists('test.txt'):
errors.append("Song database (test.txt) not found")
if errors:
print("Configuration errors:")
for error in errors:
print(f" - {error}")
sys.exit(1)
if __name__ == '__main__':
validate_config()
app.run(debug=True)Modify algorithmia.py:
# Use different algorithm version
algo = client.algo('deeplearning/EmotionRecognitionCNNMBP/2.0.0')
# Or different algorithm entirely
algo = client.algo('deeplearning/AlternativeEmotionModel/1.0.0')Create library switcher:
MUSIC_LIBRARIES = {
'default': 'test.txt',
'rock': 'rock_songs.txt',
'classical': 'classical_songs.txt'
}
def get_playlist(library='default'):
db_path = MUSIC_LIBRARIES.get(library, 'test.txt')
with open(db_path, "rb") as fp:
songnames = pickle.load(fp, encoding='latin1')
# ... rest of function❌ Bad:
client = Algorithmia.client('sim123456789')✅ Good:
client = Algorithmia.client(os.getenv('ALGORITHMIA_API_KEY'))if os.getenv('FLASK_ENV') == 'production':
app.config['DEBUG'] = False
app.config['TESTING'] = False
else:
app.config['DEBUG'] = Trueassert os.getenv('ALGORITHMIA_API_KEY'), "API key required"Keep this configuration guide updated with any new options.
class Config:
SECRET_KEY = os.getenv('FLASK_SECRET_KEY')
DEBUG = False
TESTING = False
class DevelopmentConfig(Config):
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
app.config.from_object(DevelopmentConfig)