python service managment on client, port configuration

This commit is contained in:
michalcourson
2026-02-24 18:08:58 -05:00
parent d49ac95fa2
commit 47cdaa76b6
26 changed files with 244 additions and 67 deletions

View File

@ -1,16 +1,17 @@
{
"input_device": {
"index": 49,
"name": "Microphone (Logi C615 HD WebCam)",
"max_input_channels": 1,
"default_samplerate": 48000.0
"channels": 2,
"default_samplerate": 48000,
"index": 55,
"name": "VM Mic mix (VB-Audio Voicemeeter VAIO)"
},
"save_path": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings",
"recording_length": 30,
"output_device": {
"default_samplerate": 48000,
"index": 40,
"name": "Speakers (Realtek(R) Audio)",
"max_output_channels": 2,
"default_samplerate": 48000.0
}
"name": "Speakers (Realtek(R) Audio)"
},
"http_port": 5010
}

View File

@ -10,7 +10,7 @@ class AudioRecorder:
def __new__(cls, *args, **kwargs):
if cls._instance is None:
print("Creating new AudioRecorder instance")
# print("Creating new AudioRecorder instance")
cls._instance = super().__new__(cls)
cls._instance.init()
return cls._instance
@ -22,7 +22,7 @@ class AudioRecorder:
:param sample_rate: Audio sample rate (if None, use default device sample rate)
:param channels: Number of audio channels
"""
print(f"Initializing AudioRecorder")
# print(f"Initializing AudioRecorder")
self.duration = 30
self.sample_rate = 44100
self.channels = 2
@ -42,7 +42,7 @@ class AudioRecorder:
self.stream.stop()
self.buffer = np.zeros((int(self.duration * self.sample_rate), self.channels), dtype=np.float32)
print(f"AudioRecorder initialized with duration={self.duration}s, sample_rate={self.sample_rate}Hz, channels={self.channels}")
# print(f"AudioRecorder initialized with duration={self.duration}s, sample_rate={self.sample_rate}Hz, channels={self.channels}")
self.stream = sd.InputStream(
callback=self.record_callback
)
@ -63,7 +63,8 @@ class AudioRecorder:
:param status: Recording status
"""
if status:
print(f"Recording status: {status}")
# print(f"Recording status: {status}")
pass
# Circular buffer implementation
self.buffer = np.roll(self.buffer, -frames, axis=0)
@ -128,9 +129,9 @@ class AudioRecorder:
Start continuous audio recording with circular buffer.
"""
if(self.stream.active):
print("Already recording")
# print("Already recording")
return
print('number of channels', self.channels)
# print('number of channels', self.channels)
self.stream.start()
@ -139,7 +140,7 @@ class AudioRecorder:
Stop continuous audio recording with circular buffer.
"""
if(not self.stream.active):
print("Already stopped")
# print("Already stopped")
return
self.stream.stop()

View File

@ -46,23 +46,20 @@ def main():
app.register_blueprint(device_bp)
app.register_blueprint(metadata_bp)
app.register_blueprint(settings_bp)
app.run(host='127.0.0.1', port=args.osc_port, debug=False, use_reloader=True)
app.run(host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True)
# socketio.run(app, host='127.0.0.1', port=args.osc_port, debug=False, use_reloader=True)
# Run the OSC server
try:
print(f"Starting OSC Recording Server on port {args.osc_port}")
# osc_server.run_server()
except KeyboardInterrupt:
print("\nServer stopped by user.")
except Exception as e:
print(f"Error starting server: {e}")
sys.exit(1)
# try:
# print(f"Starting OSC Recording Server on port {args.osc_port}")
# # osc_server.run_server()
# except KeyboardInterrupt:
# print("\nServer stopped by user.")
# except Exception as e:
# print(f"Error starting server: {e}")
# sys.exit(1)
if __name__ == "__main__":

View File

@ -91,7 +91,7 @@ def edit_clip_in_collection():
meta_manager = MetaDataManager()
collection_name = request.json.get('name')
clip_metadata = request.json.get('clip')
print(f"Received request to edit clip in collection '{collection_name}': {clip_metadata}")
# print(f"Received request to edit clip in collection '{collection_name}': {clip_metadata}")
try:
meta_manager.edit_clip_in_collection(collection_name, clip_metadata)
collections = meta_manager.collections

View File

@ -15,14 +15,14 @@ def start_recording():
@recording_bp.route('/record/stop', methods=['POST'])
def stop_recording():
recorder = AudioRecorder()
print('HTTP: Stopping audio recording')
# print('HTTP: Stopping audio recording')
recorder.stop_recording()
return jsonify({'status': 'recording stopped'})
@recording_bp.route('/record/save', methods=['POST'])
def save_recording():
recorder = AudioRecorder()
print('HTTP: Saving audio recording')
# print('HTTP: Saving audio recording')
saved_file = recorder.save_last_n_seconds()
return jsonify({'status': 'recording saved', 'file': saved_file})
@ -30,7 +30,7 @@ def save_recording():
@recording_bp.route('/record/status', methods=['GET'])
def recording_status():
recorder = AudioRecorder()
print('HTTP: Checking recording status')
# print('HTTP: Checking recording status')
status = 'recording' if recorder.is_recording() else 'stopped'
return jsonify({'status': status})
@ -45,7 +45,7 @@ def recording_delete():
@recording_bp.route('/playback/start', methods=['POST'])
def playback_start():
print('HTTP: Starting audio playback')
# print('HTTP: Starting audio playback')
try:
# os.remove(filename)
return jsonify({'status': 'success'})

View File

@ -16,10 +16,16 @@ def get_setting(name):
else:
return jsonify({'status': 'error', 'message': f'Setting "{name}" not found'}), 404
@settings_bp.route('/settings/<name>', methods=['POST'])
def set_setting(name):
value = request.json.get('value')
if value is None:
return jsonify({'status': 'error', 'message': 'Value is required'}), 400
SettingsManager().set_settings(name, value)
return jsonify({'status': 'success', 'name': name, 'value': value})
@settings_bp.route('/settings/update', methods=['POST'])
def set_all_settings():
settings = request.json.get('settings')
print (f"Received settings update: {settings}")
if settings is None:
return jsonify({'status': 'error', 'message': 'Settings are required'}), 400
try:
for name, value in settings.items():
print(f"Updating setting '{name}' to '{value}'")
SettingsManager().set_settings(name, value)
return jsonify({'status': 'success', 'settings': settings})
except ValueError as e:
return jsonify({'status': 'error', 'message': str(e)}), 400

View File

@ -13,6 +13,7 @@ class SettingsManager:
return cls._instance
def init(self):
# read settings file from executing directory
print("Initializing SettingsManager", os.getcwd())
self.settings_file = os.path.join(os.getcwd(), "settings.json")
if os.path.exists(self.settings_file):
with open(self.settings_file, "r") as f:
@ -46,18 +47,23 @@ class SettingsManager:
#see if input device is in "devices", if not set to the first index
if input is not None and any(d['name'] == input["name"] for d in input_devices):
print(f"Using saved input device index: {input}")
# print(f"Using saved input device index: {input}")
pass
else:
input = input_devices[0] if input_devices else None
self.settings["input_device"] = input
#see if output device is in "devices", if not set to the first index
if output is not None and any(d['name'] == output["name"] for d in output_devices):
print(f"Using saved output device index: {output}")
# print(f"Using saved output device index: {output}")
pass
else:
output = output_devices[0] if output_devices else None
self.settings["output_device"] = output
if not "http_port" in self.settings:
self.settings["http_port"] = 5010
self.save_settings()
@ -71,6 +77,8 @@ class SettingsManager:
return self.settings
def set_settings(self, name, value):
if(name not in self.settings):
raise ValueError(f"Setting '{name}' not found.")
self.settings[name] = value
self.save_settings()

View File

@ -25,11 +25,11 @@ class WindowsAudioManager:
wasapi_device_indexes = api['devices']
break
# print(f"Host APIs: {host_apis}")
print(f"WASAPI Device Indexes: {wasapi_device_indexes}")
# print(f"WASAPI Device Indexes: {wasapi_device_indexes}")
wasapi_device_indexes = set(wasapi_device_indexes) if wasapi_device_indexes is not None else set()
self.devices = [dev for dev in sd.query_devices() if dev['index'] in wasapi_device_indexes]
# self.devices = sd.query_devices()
print(f"devices: {self.devices}")
# print(f"devices: {self.devices}")
self.default_input = sd.default.device[0]
self.default_output = sd.default.device[1]