99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
import os
|
|
import time
|
|
from flask import Flask, request, send_file, jsonify
|
|
from flask_cors import CORS
|
|
from werkzeug.utils import secure_filename
|
|
from processor import AudioImageProcessor
|
|
|
|
app = Flask(__name__)
|
|
CORS(app) # Allow Svelte to communicate
|
|
|
|
# Configuration
|
|
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'uploads')
|
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
|
processor = AudioImageProcessor(UPLOAD_FOLDER)
|
|
|
|
def save_upload(file_obj):
|
|
filename = secure_filename(file_obj.filename)
|
|
path = os.path.join(app.config['UPLOAD_FOLDER'], f"{int(time.time())}_{filename}")
|
|
file_obj.save(path)
|
|
return path
|
|
|
|
@app.route('/health', methods=['GET'])
|
|
def health():
|
|
return jsonify({"status": "ok", "max_mb": 40})
|
|
|
|
# --- Endpoint 1: Create Art (Optional: Embed Audio in it) ---
|
|
@app.route('/api/generate-art', methods=['POST'])
|
|
def generate_art():
|
|
if 'audio' not in request.files:
|
|
return jsonify({"error": "No audio file provided"}), 400
|
|
|
|
audio_file = request.files['audio']
|
|
should_embed = request.form.get('embed', 'false').lower() == 'true'
|
|
|
|
try:
|
|
# 1. Save Audio
|
|
audio_path = save_upload(audio_file)
|
|
|
|
# 2. Generate Art
|
|
art_path = processor.generate_spectrogram(audio_path)
|
|
|
|
# 3. If Embed requested, run Steganography immediately using the art as host
|
|
final_path = art_path
|
|
if should_embed:
|
|
final_path = processor.encode_stego(audio_path, art_path)
|
|
|
|
return send_file(final_path, mimetype='image/png')
|
|
|
|
except Exception as e:
|
|
return jsonify({"error": str(e)}), 500
|
|
|
|
# --- Endpoint 2: Format Shift (Audio -> Static) ---
|
|
@app.route('/api/shift', methods=['POST'])
|
|
def shift_format():
|
|
if 'file' not in request.files:
|
|
return jsonify({"error": "No file provided"}), 400
|
|
|
|
try:
|
|
f_path = save_upload(request.files['file'])
|
|
img_path = processor.encode_shift(f_path)
|
|
return send_file(img_path, mimetype='image/png')
|
|
except Exception as e:
|
|
return jsonify({"error": str(e)}), 500
|
|
|
|
# --- Endpoint 3: Steganography (Audio + Custom Host) ---
|
|
@app.route('/api/hide', methods=['POST'])
|
|
def hide_data():
|
|
if 'data' not in request.files or 'host' not in request.files:
|
|
return jsonify({"error": "Requires 'data' and 'host' files"}), 400
|
|
|
|
try:
|
|
data_path = save_upload(request.files['data'])
|
|
host_path = save_upload(request.files['host'])
|
|
|
|
stego_path = processor.encode_stego(data_path, host_path)
|
|
return send_file(stego_path, mimetype='image/png')
|
|
except Exception as e:
|
|
return jsonify({"error": str(e)}), 500
|
|
|
|
# --- Endpoint 4: Decode (Universal) ---
|
|
@app.route('/api/decode', methods=['POST'])
|
|
def decode():
|
|
if 'image' not in request.files:
|
|
return jsonify({"error": "No image provided"}), 400
|
|
|
|
try:
|
|
img_path = save_upload(request.files['image'])
|
|
restored_path = processor.decode_image(img_path)
|
|
|
|
# Determine mimetype based on extension for browser friendliness
|
|
filename = os.path.basename(restored_path)
|
|
return send_file(restored_path, as_attachment=True, download_name=filename)
|
|
except Exception as e:
|
|
return jsonify({"error": str(e)}), 500
|
|
|
|
if __name__ == '__main__':
|
|
# Threaded=True is important for processing images without blocking
|
|
app.run(debug=True, port=5000, threaded=True)
|