Improve UX: hide console window and fade connection status
- Hide console window on compiled desktop app (console=False in spec) - Add 20-second auto-fade to "Connected" status in OBS display - Keep "Disconnected" status visible until reconnection - Add PM2 deployment configuration and documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -137,7 +137,7 @@ exe = EXE(
|
|||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False,
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=True,
|
upx=True,
|
||||||
console=True, # Set to False to hide console window
|
console=False, # Hide console window for GUI application
|
||||||
disable_windowed_traceback=False,
|
disable_windowed_traceback=False,
|
||||||
argv_emulation=False,
|
argv_emulation=False,
|
||||||
target_arch=None,
|
target_arch=None,
|
||||||
|
|||||||
477
server/nodejs/DEPLOY.md
Normal file
477
server/nodejs/DEPLOY.md
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
# Deploying Node.js Transcription Server
|
||||||
|
|
||||||
|
## Quick Deploy with PM2
|
||||||
|
|
||||||
|
### Step 1: Upload Files to Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your local machine:
|
||||||
|
rsync -avz --exclude 'node_modules' --exclude 'data' \
|
||||||
|
server/nodejs/ shadowdao@your-server:/home/shadowdao/local-transcription/server/nodejs/
|
||||||
|
```
|
||||||
|
|
||||||
|
Or manually upload:
|
||||||
|
- `server.js`
|
||||||
|
- `package.json`
|
||||||
|
- `ecosystem.config.js`
|
||||||
|
|
||||||
|
### Step 2: Install Dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH into your server
|
||||||
|
ssh shadowdao@your-server
|
||||||
|
|
||||||
|
# Navigate to directory
|
||||||
|
cd /home/shadowdao/local-transcription/server/nodejs
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install --production
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create Log Directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create log directory if it doesn't exist
|
||||||
|
mkdir -p /home/shadowdao/logs/transcription
|
||||||
|
chmod 755 /home/shadowdao/logs/transcription
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Create Data Directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create data directory for room storage
|
||||||
|
mkdir -p /home/shadowdao/local-transcription/server/nodejs/data
|
||||||
|
chmod 755 /home/shadowdao/local-transcription/server/nodejs/data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Update ecosystem.config.js Paths
|
||||||
|
|
||||||
|
Edit `ecosystem.config.js` and update these paths:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
cwd: '/home/shadowdao/local-transcription/server/nodejs', // ← Your actual path
|
||||||
|
DATA_DIR: '/home/shadowdao/local-transcription/server/nodejs/data',
|
||||||
|
log_file: '/home/shadowdao/logs/transcription/app.log', // ← Your log path
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Start with PM2
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start the server
|
||||||
|
pm2 start ecosystem.config.js --env production
|
||||||
|
|
||||||
|
# Save PM2 configuration
|
||||||
|
pm2 save
|
||||||
|
|
||||||
|
# Set up PM2 to start on boot (first time only)
|
||||||
|
pm2 startup
|
||||||
|
# Follow the instructions it prints
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
pm2 status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PM2 Management Commands
|
||||||
|
|
||||||
|
### Check Status
|
||||||
|
```bash
|
||||||
|
pm2 status # List all apps
|
||||||
|
pm2 show transcription-server # Detailed info
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
```bash
|
||||||
|
pm2 logs transcription-server # Live logs
|
||||||
|
pm2 logs transcription-server --lines 100 # Last 100 lines
|
||||||
|
pm2 logs transcription-server --err # Errors only
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart/Stop
|
||||||
|
```bash
|
||||||
|
pm2 restart transcription-server
|
||||||
|
pm2 stop transcription-server
|
||||||
|
pm2 delete transcription-server # Remove from PM2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitor
|
||||||
|
```bash
|
||||||
|
pm2 monit # Real-time monitoring (CPU, memory, logs)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Code
|
||||||
|
```bash
|
||||||
|
# After uploading new code:
|
||||||
|
pm2 restart transcription-server
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### Change Port
|
||||||
|
|
||||||
|
Edit `ecosystem.config.js`:
|
||||||
|
```javascript
|
||||||
|
env_production: {
|
||||||
|
PORT: 3001, // ← Change port here
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then restart:
|
||||||
|
```bash
|
||||||
|
pm2 restart transcription-server
|
||||||
|
```
|
||||||
|
|
||||||
|
### Increase Memory Limit
|
||||||
|
|
||||||
|
If you get "JavaScript heap out of memory" errors:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
max_memory_restart: '1G', // ← Increase from 512M
|
||||||
|
env_production: {
|
||||||
|
NODE_OPTIONS: '--max-old-space-size=800' // ← Increase from 400
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enable File Watching (Development)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
watch: true,
|
||||||
|
ignore_watch: ['node_modules', 'data', 'logs'],
|
||||||
|
```
|
||||||
|
|
||||||
|
**Warning:** Don't use in production (unnecessary restarts)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nginx Reverse Proxy (Optional)
|
||||||
|
|
||||||
|
To serve on port 80/443 with SSL:
|
||||||
|
|
||||||
|
### Create Nginx Config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /etc/nginx/sites-available/transcription
|
||||||
|
```
|
||||||
|
|
||||||
|
Add:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name transcription.yourdomain.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:3000;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
|
||||||
|
# WebSocket support
|
||||||
|
proxy_read_timeout 86400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable:
|
||||||
|
```bash
|
||||||
|
sudo ln -s /etc/nginx/sites-available/transcription /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add SSL with Let's Encrypt
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install certbot python3-certbot-nginx
|
||||||
|
sudo certbot --nginx -d transcription.yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Firewall Configuration
|
||||||
|
|
||||||
|
### Allow Port 3000
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# UFW
|
||||||
|
sudo ufw allow 3000/tcp
|
||||||
|
|
||||||
|
# iptables
|
||||||
|
sudo iptables -A INPUT -p tcp --dport 3000 -j ACCEPT
|
||||||
|
sudo iptables-save
|
||||||
|
```
|
||||||
|
|
||||||
|
### Or Use Nginx (Port 80/443)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 'Nginx Full'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
You can add environment variables in `ecosystem.config.js`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
env_production: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
PORT: 3000,
|
||||||
|
|
||||||
|
// Custom variables
|
||||||
|
MAX_ROOMS: 100,
|
||||||
|
ROOM_CLEANUP_INTERVAL: 7200000, // 2 hours in ms
|
||||||
|
MAX_CLIENTS_PER_ROOM: 50,
|
||||||
|
|
||||||
|
// Data storage
|
||||||
|
DATA_DIR: '/home/shadowdao/transcription-data',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Access in `server.js`:
|
||||||
|
```javascript
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
const MAX_ROOMS = process.env.MAX_ROOMS || 100;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Monitoring & Maintenance
|
||||||
|
|
||||||
|
### Check Server is Running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3000
|
||||||
|
# Should see HTML response
|
||||||
|
|
||||||
|
curl http://localhost:3000/api/list?room=test
|
||||||
|
# Should see: {"transcriptions":[]}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check WebSocket
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install wscat
|
||||||
|
npm install -g wscat
|
||||||
|
|
||||||
|
# Test WebSocket connection
|
||||||
|
wscat -c ws://localhost:3000/ws?room=test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitor Resources
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pm2 monit # PM2 built-in monitor
|
||||||
|
|
||||||
|
# Or use htop
|
||||||
|
htop # Look for "node" process
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log Rotation
|
||||||
|
|
||||||
|
PM2 handles log rotation automatically, but you can configure it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pm2 install pm2-logrotate
|
||||||
|
|
||||||
|
pm2 set pm2-logrotate:max_size 10M
|
||||||
|
pm2 set pm2-logrotate:retain 7
|
||||||
|
pm2 set pm2-logrotate:compress true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Server Won't Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
pm2 logs transcription-server --err
|
||||||
|
|
||||||
|
# Common issues:
|
||||||
|
# 1. Port already in use
|
||||||
|
sudo lsof -i :3000
|
||||||
|
# Kill the process or change port
|
||||||
|
|
||||||
|
# 2. Missing dependencies
|
||||||
|
cd /home/shadowdao/local-transcription/server/nodejs
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 3. Permission issues
|
||||||
|
chmod 755 server.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### WebSocket Not Working
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if server is listening
|
||||||
|
netstat -tlnp | grep 3000
|
||||||
|
|
||||||
|
# Check Nginx config if using reverse proxy
|
||||||
|
sudo nginx -t
|
||||||
|
|
||||||
|
# Check firewall
|
||||||
|
sudo ufw status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Out of Memory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check memory usage
|
||||||
|
pm2 show transcription-server
|
||||||
|
|
||||||
|
# Increase in ecosystem.config.js:
|
||||||
|
max_memory_restart: '1G',
|
||||||
|
NODE_OPTIONS: '--max-old-space-size=800'
|
||||||
|
|
||||||
|
# Restart
|
||||||
|
pm2 restart transcription-server
|
||||||
|
```
|
||||||
|
|
||||||
|
### Too Many Rooms (Disk Full)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check data directory size
|
||||||
|
du -sh /home/shadowdao/local-transcription/server/nodejs/data
|
||||||
|
|
||||||
|
# Clean old rooms manually
|
||||||
|
cd /home/shadowdao/local-transcription/server/nodejs/data
|
||||||
|
find . -name "room_*.json" -mtime +1 -delete # Delete files older than 1 day
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Production Checklist
|
||||||
|
|
||||||
|
- [ ] Dependencies installed (`npm install --production`)
|
||||||
|
- [ ] Log directory created and writable
|
||||||
|
- [ ] Data directory created and writable
|
||||||
|
- [ ] Paths updated in `ecosystem.config.js`
|
||||||
|
- [ ] PM2 started (`pm2 start ecosystem.config.js --env production`)
|
||||||
|
- [ ] PM2 saved (`pm2 save`)
|
||||||
|
- [ ] PM2 startup configured (`pm2 startup`)
|
||||||
|
- [ ] Firewall configured (port 3000 or Nginx)
|
||||||
|
- [ ] Nginx reverse proxy configured (optional)
|
||||||
|
- [ ] SSL certificate installed (optional)
|
||||||
|
- [ ] Test with `curl http://your-server:3000`
|
||||||
|
- [ ] Test WebSocket with browser display page
|
||||||
|
- [ ] Monitor for 24 hours to ensure stability
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup & Restore
|
||||||
|
|
||||||
|
### Backup Room Data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup data directory
|
||||||
|
tar -czf transcription-backup-$(date +%Y%m%d).tar.gz \
|
||||||
|
/home/shadowdao/local-transcription/server/nodejs/data
|
||||||
|
|
||||||
|
# Move to backup location
|
||||||
|
mv transcription-backup-*.tar.gz /home/shadowdao/backups/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Automated Backup (Cron)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
crontab -e
|
||||||
|
```
|
||||||
|
|
||||||
|
Add:
|
||||||
|
```cron
|
||||||
|
# Backup transcription data daily at 2 AM
|
||||||
|
0 2 * * * tar -czf /home/shadowdao/backups/transcription-$(date +\%Y\%m\%d).tar.gz /home/shadowdao/local-transcription/server/nodejs/data
|
||||||
|
|
||||||
|
# Delete backups older than 7 days
|
||||||
|
0 3 * * * find /home/shadowdao/backups/transcription-*.tar.gz -mtime +7 -delete
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Tuning
|
||||||
|
|
||||||
|
### For High Traffic (100+ concurrent users)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// In ecosystem.config.js:
|
||||||
|
max_memory_restart: '2G',
|
||||||
|
env_production: {
|
||||||
|
NODE_OPTIONS: '--max-old-space-size=1600'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cluster Mode (Multiple CPU Cores)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
exec_mode: 'cluster',
|
||||||
|
instances: 2, // Use 2 CPU cores
|
||||||
|
```
|
||||||
|
|
||||||
|
**Warning:** Cluster mode requires sticky sessions for WebSockets. Use single instance unless you implement Redis for session sharing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
If issues persist:
|
||||||
|
|
||||||
|
1. Check logs: `pm2 logs transcription-server`
|
||||||
|
2. Check server status: `pm2 show transcription-server`
|
||||||
|
3. Test manually: `node server.js` (see direct output)
|
||||||
|
4. Check Node.js version: `node --version` (needs 14+)
|
||||||
|
5. Check port availability: `sudo lsof -i :3000`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example Deploy Script
|
||||||
|
|
||||||
|
Create `deploy.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Deploy transcription server
|
||||||
|
|
||||||
|
SERVER="shadowdao@your-server"
|
||||||
|
REMOTE_PATH="/home/shadowdao/local-transcription/server/nodejs"
|
||||||
|
|
||||||
|
echo "Uploading files..."
|
||||||
|
rsync -avz --exclude 'node_modules' --exclude 'data' \
|
||||||
|
./ $SERVER:$REMOTE_PATH/
|
||||||
|
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
ssh $SERVER "cd $REMOTE_PATH && npm install --production"
|
||||||
|
|
||||||
|
echo "Restarting server..."
|
||||||
|
ssh $SERVER "pm2 restart transcription-server"
|
||||||
|
|
||||||
|
echo "Checking status..."
|
||||||
|
ssh $SERVER "pm2 status transcription-server"
|
||||||
|
|
||||||
|
echo "Deployment complete!"
|
||||||
|
```
|
||||||
|
|
||||||
|
Make executable:
|
||||||
|
```bash
|
||||||
|
chmod +x deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
```bash
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Server should now be accessible at:**
|
||||||
|
- Homepage: `http://your-server:3000`
|
||||||
|
- API: `http://your-server:3000/api/send`
|
||||||
|
- Display: `http://your-server:3000/display?room=test`
|
||||||
92
server/nodejs/QUICK_DEPLOY.md
Normal file
92
server/nodejs/QUICK_DEPLOY.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Quick Deploy Guide
|
||||||
|
|
||||||
|
## TL;DR - Copy & Paste These Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Upload files to server
|
||||||
|
cd /home/jknapp/code/local-transcription
|
||||||
|
rsync -avz --exclude 'node_modules' --exclude 'data' \
|
||||||
|
server/nodejs/ shadowdao@YOUR_SERVER:/home/shadowdao/local-transcription/server/nodejs/
|
||||||
|
|
||||||
|
# 2. SSH into server
|
||||||
|
ssh shadowdao@YOUR_SERVER
|
||||||
|
|
||||||
|
# 3. Install dependencies
|
||||||
|
cd /home/shadowdao/local-transcription/server/nodejs
|
||||||
|
npm install --production
|
||||||
|
|
||||||
|
# 4. Create directories
|
||||||
|
mkdir -p /home/shadowdao/logs/transcription
|
||||||
|
mkdir -p data
|
||||||
|
|
||||||
|
# 5. Start with PM2
|
||||||
|
pm2 start ecosystem.config.js --env production
|
||||||
|
pm2 save
|
||||||
|
pm2 startup # Run the command it prints
|
||||||
|
|
||||||
|
# 6. Check status
|
||||||
|
pm2 status
|
||||||
|
pm2 logs transcription-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test It Works
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test HTTP
|
||||||
|
curl http://localhost:3000
|
||||||
|
|
||||||
|
# Test API
|
||||||
|
curl http://localhost:3000/api/list?room=test
|
||||||
|
|
||||||
|
# View in browser
|
||||||
|
# http://YOUR_SERVER_IP:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
## PM2 Cheat Sheet
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pm2 status # Check status
|
||||||
|
pm2 logs transcription-server # View logs
|
||||||
|
pm2 restart transcription-server # Restart
|
||||||
|
pm2 stop transcription-server # Stop
|
||||||
|
pm2 monit # Monitor resources
|
||||||
|
```
|
||||||
|
|
||||||
|
## Firewall (if needed)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 3000/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update After Code Changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On your local machine:
|
||||||
|
rsync -avz --exclude 'node_modules' --exclude 'data' \
|
||||||
|
server/nodejs/ shadowdao@YOUR_SERVER:/home/shadowdao/local-transcription/server/nodejs/
|
||||||
|
|
||||||
|
# On server:
|
||||||
|
ssh shadowdao@YOUR_SERVER
|
||||||
|
pm2 restart transcription-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Server won't start?**
|
||||||
|
```bash
|
||||||
|
pm2 logs transcription-server --err
|
||||||
|
```
|
||||||
|
|
||||||
|
**Port already in use?**
|
||||||
|
```bash
|
||||||
|
sudo lsof -i :3000
|
||||||
|
# Kill process or change port in ecosystem.config.js
|
||||||
|
```
|
||||||
|
|
||||||
|
**Out of memory?**
|
||||||
|
Edit `ecosystem.config.js`:
|
||||||
|
```javascript
|
||||||
|
max_memory_restart: '1G', // Increase from 512M
|
||||||
|
```
|
||||||
|
|
||||||
|
See [DEPLOY.md](DEPLOY.md) for complete guide.
|
||||||
37
server/nodejs/ecosystem.config.js
Normal file
37
server/nodejs/ecosystem.config.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [{
|
||||||
|
name: 'transcription-server',
|
||||||
|
script: 'server.js',
|
||||||
|
cwd: '/home/shadowdao/local-transcription/server/nodejs', // ← Update this path
|
||||||
|
exec_mode: 'fork',
|
||||||
|
instances: 1,
|
||||||
|
autorestart: true,
|
||||||
|
watch: false,
|
||||||
|
max_memory_restart: '512M', // ← Increased (transcription data in memory)
|
||||||
|
kill_timeout: 5000, // ← Give time for WebSocket cleanup
|
||||||
|
wait_ready: false,
|
||||||
|
listen_timeout: 5000,
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'development',
|
||||||
|
PORT: 3000,
|
||||||
|
DATA_DIR: '/home/shadowdao/local-transcription/server/nodejs/data', // ← Data directory
|
||||||
|
NODE_OPTIONS: '--max-old-space-size=400' // ← Increased memory
|
||||||
|
},
|
||||||
|
env_production: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
PORT: 3000,
|
||||||
|
DATA_DIR: '/home/shadowdao/local-transcription/server/nodejs/data',
|
||||||
|
NODE_OPTIONS: '--max-old-space-size=400'
|
||||||
|
},
|
||||||
|
log_file: '/home/shadowdao/logs/transcription/app.log',
|
||||||
|
error_file: '/home/shadowdao/logs/transcription/error.log',
|
||||||
|
out_file: '/home/shadowdao/logs/transcription/out.log',
|
||||||
|
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
||||||
|
log_type: 'json',
|
||||||
|
merge_logs: true,
|
||||||
|
max_restarts: 10, // ← More retries (WebSocket can be finicky)
|
||||||
|
min_uptime: '10s',
|
||||||
|
// Graceful shutdown for WebSocket connections
|
||||||
|
shutdown_with_message: true
|
||||||
|
}]
|
||||||
|
};
|
||||||
@@ -687,9 +687,11 @@ app.get('/display', (req, res) => {
|
|||||||
background: rgba(0, 0, 0, 0.8);
|
background: rgba(0, 0, 0, 0.8);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
transition: opacity 2s ease-out;
|
||||||
}
|
}
|
||||||
#status.connected { color: #4CAF50; }
|
#status.connected { color: #4CAF50; }
|
||||||
#status.disconnected { color: #f44336; }
|
#status.disconnected { color: #f44336; }
|
||||||
|
#status.hidden { opacity: 0; pointer-events: none; }
|
||||||
@keyframes slideIn {
|
@keyframes slideIn {
|
||||||
from { opacity: 0; transform: translateY(-10px); }
|
from { opacity: 0; transform: translateY(-10px); }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
to { opacity: 1; transform: translateY(0); }
|
||||||
@@ -761,6 +763,8 @@ app.get('/display', (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let statusHideTimeout = null;
|
||||||
|
|
||||||
function connect() {
|
function connect() {
|
||||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
const ws = new WebSocket(\`\${protocol}//\${window.location.host}/ws?room=\${encodeURIComponent(room)}\`);
|
const ws = new WebSocket(\`\${protocol}//\${window.location.host}/ws?room=\${encodeURIComponent(room)}\`);
|
||||||
@@ -768,6 +772,16 @@ app.get('/display', (req, res) => {
|
|||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
statusEl.textContent = '🟢 Connected';
|
statusEl.textContent = '🟢 Connected';
|
||||||
statusEl.className = 'connected';
|
statusEl.className = 'connected';
|
||||||
|
|
||||||
|
// Clear any existing timeout
|
||||||
|
if (statusHideTimeout) {
|
||||||
|
clearTimeout(statusHideTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade out after 20 seconds
|
||||||
|
statusHideTimeout = setTimeout(() => {
|
||||||
|
statusEl.classList.add('hidden');
|
||||||
|
}, 20000);
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onmessage = (event) => {
|
ws.onmessage = (event) => {
|
||||||
@@ -780,6 +794,12 @@ app.get('/display', (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ws.onclose = () => {
|
ws.onclose = () => {
|
||||||
|
// Clear hide timeout on disconnect
|
||||||
|
if (statusHideTimeout) {
|
||||||
|
clearTimeout(statusHideTimeout);
|
||||||
|
statusHideTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
statusEl.textContent = '🔴 Disconnected';
|
statusEl.textContent = '🔴 Disconnected';
|
||||||
statusEl.className = 'disconnected';
|
statusEl.className = 'disconnected';
|
||||||
setTimeout(connect, 3000);
|
setTimeout(connect, 3000);
|
||||||
|
|||||||
Reference in New Issue
Block a user