feat: Integrar LiveKit y actualizar URLs en el panel de transmisión y API
This commit is contained in:
parent
f57ce90c11
commit
396a803b1c
1
package-lock.json
generated
1
package-lock.json
generated
@ -11875,6 +11875,7 @@
|
|||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"joi": "^17.11.0",
|
"joi": "^17.11.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"livekit-server-sdk": "^2.14.0",
|
||||||
"socket.io": "^4.6.2",
|
"socket.io": "^4.6.2",
|
||||||
"stripe": "^14.9.0",
|
"stripe": "^14.9.0",
|
||||||
"winston": "^3.11.0"
|
"winston": "^3.11.0"
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"joi": "^17.11.0",
|
"joi": "^17.11.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"livekit-server-sdk": "^2.14.0",
|
||||||
"socket.io": "^4.6.2",
|
"socket.io": "^4.6.2",
|
||||||
"stripe": "^14.9.0",
|
"stripe": "^14.9.0",
|
||||||
"winston": "^3.11.0"
|
"winston": "^3.11.0"
|
||||||
|
|||||||
@ -15,6 +15,9 @@ const allowedOrigins = process.env.FRONTEND_URLS?.split(',') || ['http://localho
|
|||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
if (!allowedOrigins.includes('http://localhost:3020')) allowedOrigins.push('http://localhost:3020')
|
if (!allowedOrigins.includes('http://localhost:3020')) allowedOrigins.push('http://localhost:3020')
|
||||||
if (!allowedOrigins.includes('http://localhost:3021')) allowedOrigins.push('http://localhost:3021')
|
if (!allowedOrigins.includes('http://localhost:3021')) allowedOrigins.push('http://localhost:3021')
|
||||||
|
if (!allowedOrigins.includes('http://localhost:5175')) allowedOrigins.push('http://localhost:5175')
|
||||||
|
if (!allowedOrigins.includes('https://avanzacast-studio.bfzqqk.easypanel.host')) allowedOrigins.push('https://avanzacast-studio.bfzqqk.easypanel.host')
|
||||||
|
if (!allowedOrigins.includes('https://avanzacast-broadcastpanel.bfzqqk.easypanel.host')) allowedOrigins.push('https://avanzacast-broadcastpanel.bfzqqk.easypanel.host')
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(cors({
|
app.use(cors({
|
||||||
@ -44,6 +47,56 @@ app.get('/api/v1', (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// LiveKit token generation endpoint
|
||||||
|
app.get('/api/token', async (req, res) => {
|
||||||
|
const { room, username } = req.query;
|
||||||
|
|
||||||
|
if (!room || typeof room !== 'string') {
|
||||||
|
return res.status(400).json({ error: 'Room name is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!username || typeof username !== 'string') {
|
||||||
|
return res.status(400).json({ error: 'Username is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement actual LiveKit token generation
|
||||||
|
// For now, return a placeholder response
|
||||||
|
const LIVEKIT_API_KEY = process.env.LIVEKIT_API_KEY;
|
||||||
|
const LIVEKIT_API_SECRET = process.env.LIVEKIT_API_SECRET;
|
||||||
|
|
||||||
|
if (!LIVEKIT_API_KEY || !LIVEKIT_API_SECRET) {
|
||||||
|
console.error('⚠️ LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be set in environment variables');
|
||||||
|
return res.status(500).json({ error: 'LiveKit credentials not configured' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Import AccessToken from livekit-server-sdk
|
||||||
|
const { AccessToken } = await import('livekit-server-sdk');
|
||||||
|
|
||||||
|
const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, {
|
||||||
|
identity: username,
|
||||||
|
name: username,
|
||||||
|
});
|
||||||
|
|
||||||
|
at.addGrant({
|
||||||
|
room,
|
||||||
|
roomJoin: true,
|
||||||
|
canPublish: true,
|
||||||
|
canSubscribe: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const token = await at.toJwt();
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
token,
|
||||||
|
url: process.env.LIVEKIT_URL || 'ws://localhost:7880',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error generating LiveKit token:', error);
|
||||||
|
return res.status(500).json({ error: 'Failed to generate token' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Minimal LiveKit-related endpoints (placeholder implementation)
|
// Minimal LiveKit-related endpoints (placeholder implementation)
|
||||||
app.get('/api/v1/livekit/rooms', (req, res) => {
|
app.get('/api/v1/livekit/rooms', (req, res) => {
|
||||||
const roomName = typeof req.query.roomName === 'string' ? req.query.roomName : undefined;
|
const roomName = typeof req.query.roomName === 'string' ? req.query.roomName : undefined;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const Studio: React.FC = () => {
|
|||||||
localStorage.setItem('avanzacast_room', roomName)
|
localStorage.setItem('avanzacast_room', roomName)
|
||||||
|
|
||||||
// Redirigir al studio-panel (puerto 3001)
|
// Redirigir al studio-panel (puerto 3001)
|
||||||
const studioUrl = `http://localhost:3001?user=${encodeURIComponent(userName)}&room=${encodeURIComponent(roomName)}`
|
const studioUrl = `https://avanzacast-studio.bfzqqk.easypanel.host?user=${encodeURIComponent(userName)}&room=${encodeURIComponent(roomName)}`
|
||||||
window.location.href = studioUrl
|
window.location.href = studioUrl
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ const TransmissionsTable: React.FC<Props> = ({ transmissions, onDelete, onUpdate
|
|||||||
|
|
||||||
console.log('[BroadcastPanel] Solicitando token:', { room: decodeURIComponent(room), user: decodeURIComponent(user) })
|
console.log('[BroadcastPanel] Solicitando token:', { room: decodeURIComponent(room), user: decodeURIComponent(user) })
|
||||||
|
|
||||||
const TOKEN_SERVER = import.meta.env.VITE_TOKEN_SERVER_URL || 'https://avanzacast-studio.bfzqqk.easypanel.host'
|
const TOKEN_SERVER = import.meta.env.VITE_TOKEN_SERVER_URL || 'https://avanzacast-servertokens.bfzqqk.easypanel.host'
|
||||||
const tokenUrl = `${TOKEN_SERVER.replace(/\/$/, '')}/api/token?room=${room}&username=${user}`
|
const tokenUrl = `${TOKEN_SERVER.replace(/\/$/, '')}/api/token?room=${room}&username=${user}`
|
||||||
const tokenRes = await fetch(tokenUrl)
|
const tokenRes = await fetch(tokenUrl)
|
||||||
if (!tokenRes.ok) throw new Error('No se pudo obtener token')
|
if (!tokenRes.ok) throw new Error('No se pudo obtener token')
|
||||||
|
|||||||
@ -37,6 +37,11 @@ export default defineConfig({
|
|||||||
server: {
|
server: {
|
||||||
port: 5175,
|
port: 5175,
|
||||||
host: true,
|
host: true,
|
||||||
|
allowedHosts: [
|
||||||
|
'localhost',
|
||||||
|
'.easypanel.host',
|
||||||
|
'avanzacast-broadcastpanel.bfzqqk.easypanel.host'
|
||||||
|
],
|
||||||
fs: {
|
fs: {
|
||||||
// Allow serving files from the shared folder when mounted in Docker
|
// Allow serving files from the shared folder when mounted in Docker
|
||||||
allow: [
|
allow: [
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
import type { LoginCredentials, RegisterData, AuthResponse, ApiResponse } from '@avanzacast/shared-types';
|
import type { LoginCredentials, RegisterData, AuthResponse, ApiResponse } from '@avanzacast/shared-types';
|
||||||
import { getAuthHeader } from './auth';
|
import { getAuthHeader } from './auth';
|
||||||
|
|
||||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:4000/api/v1';
|
const API_BASE_URL = import.meta.env.VITE_API_URL || 'https://avanzacast-servertokens.bfzqqk.easypanel.host/api/v1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cliente HTTP para hacer peticiones a la API
|
* Cliente HTTP para hacer peticiones a la API
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user