Thank you for your reply. I have been tinkering with it and I managed to get to the point where the client and server exchange sdp and even manage to get iceconnection connected on client, all through api calls from client to my middleman api, but janus api just hangs on this:
Creating new session: 7089357887750896; 0x7f24000d70
Creating new handle in session 7089357887750896: 7584922528700476; 0x7f24000d70 0x7f70002210
[7584922528700476] Creating ICE agent (ICE Full mode, controlling)
[WARN] [7584922528700476] Waiting for candidates-done callback... (slow gathering, are you using STUN or TURN for Janus too, instead of just for users? Consider enabling full-trickle instead)
[WARN] [7584922528700476] Still waiting for candidates-done callback... (slow gathering, are you using STUN or TURN for Janus too, instead of just for users? Consider enabling full-trickle instead)
[WARN] [7584922528700476] Still waiting for candidates-done callback... (slow gathering, are you using STUN or TURN for Janus too, instead of just for users? Consider enabling full-trickle instead)
[WARN] [7584922528700476] Still waiting for candidates-done callback... (slow gathering, are you using STUN or TURN for Janus too, instead of just for users? Consider enabling full-trickle instead)
[WARN] [7584922528700476] Waited 5s for candidates, that's way too much... going on with what we have (WebRTC setup might fail)
here is my api code, any idea why my .on never triggers? I was following the janode example but it doesnt work in my code, rather I never see the logs:
import express from 'express';
import http from 'http';
import Janode from 'janode';
import StreamingPlugin from 'janode/plugins/streaming';
import { fileURLToPath } from 'url';
import { dirname, basename } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const { Logger } = Janode;
const LOG_NS = `[${basename(__filename)}]`;
import cors from 'cors';
const connection = await Janode.connect({
is_admin: false,
address: {
url: 'ws://localhost:8188/',
apisecret: 'secret'
}
});
// Map to store active sessions for each user
const userSessions = new Map();
let session;
let streamingHandle;
const createSessionAndAttachPlugin = async (userId) => {
if (!userSessions.has(userId)) {
session = await connection.create();
// Attach to a plugin using the plugin descriptor
streamingHandle = await session.attach(StreamingPlugin);
userSessions.set(userId, { session, streamingHandle });
return streamingHandle;
} else {
return userSessions.get(userId).streamingHandle;
}
};
const createOffer = async (userId) => {
if (userSessions.has(userId)) {
const { streamingHandle } = userSessions.get(userId);
const w = await streamingHandle.watch({ id: 99 });
return w.jsep;
} else {
throw new Error('Streaming handle not available for this user.');
}
};
const startStream = async (userId, answer) => {
if (userSessions.has(userId)) {
const { streamingHandle } = userSessions.get(userId);
streamingHandle.on(Janode.EVENT.HANDLE_TRICKLE, evtdata => Logger.info(`${LOG_NS} ${streamingHandle.name} trickle event ${JSON.stringify(evtdata)}`));
const start = await streamingHandle.start(99, answer);
return 'Stream started successfully';
} else {
throw new Error('Streaming handle not available for this user.');
}
};
const doTrickle = async (userId, candidate) => {
if (userSessions.has(userId)) {
const { streamingHandle } = userSessions.get(userId);
const trickle = await streamingHandle.trickle(candidate);
return 'Trickle started successfully';
} else {
throw new Error('Streaming handle not available for this user.');
}
};
const doTrickleComplete = async (userId) => {
if (userSessions.has(userId)) {
const { streamingHandle } = userSessions.get(userId);
const tricklecomplete = await streamingHandle.trickleComplete();
return 'Trickle completed successfully';
} else {
throw new Error('Streaming handle not available for this user.');
}
};
const app = express();
// Use CORS middleware
app.use(cors());
// Middleware to parse JSON requests
app.use(express.json());
// Handle incoming client requests
app.post('/advanced/watchstream', async (req, res) => {
try {
const userId = req.body.userId;
const streamingHandle = await createSessionAndAttachPlugin(userId);
const offer = await createOffer(userId);
res.status(200).json(offer);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/advanced/startstream', async (req, res) => {
try {
const userId = req.body.userId;
const answer = req.body.answer;
const result = await startStream(userId, answer);
const response = {"hello":"world"};
res.status(200).json(response);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/advanced/sendcandidate', async (req, res) => {
try {
const candidate = req.body.candidate;
const userId = req.body.userId;
const response = await doTrickle(userId, candidate);
res.status(200).json("test");
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/advanced/rtctricklecomplete', async (req, res) => {
try {
const userId = req.body.userId;
const response = await doTrickleComplete(userId);
res.status(200).json("test");
} catch (error) {
res.status(500).json({ error: error.message });
}
});
const server = http.createServer(app);
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Thank you again for your time.