mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
Front end API implementation (draft)
This commit is contained in:
@@ -36,6 +36,18 @@ export function Dashboard({
|
||||
}
|
||||
};
|
||||
|
||||
const formatTime = (seconds) => {
|
||||
let hours = Math.floor(seconds / 3600);
|
||||
let minutes = Math.floor((seconds % 3600) / 60);
|
||||
let secs = Math.floor(seconds % 60);
|
||||
|
||||
let timeString = `${hours > 0 ? hours + ":" : ""}${minutes
|
||||
.toString()
|
||||
.padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
|
||||
|
||||
return timeString;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative h-[60svh] w-3/4 flex flex-col">
|
||||
@@ -68,7 +80,7 @@ export function Dashboard({
|
||||
className="flex justify-between items-center cursor-pointer px-4"
|
||||
onClick={() => setOpenIndex(openIndex === index ? null : index)}
|
||||
>
|
||||
<div className="w-1/4">{item.timestamp}</div>
|
||||
<div className="w-1/4">{formatTime(item.timestamp)}</div>
|
||||
<div className="w-3/4 flex justify-between items-center">
|
||||
{item.title}
|
||||
<FontAwesomeIcon
|
||||
|
||||
43
www/app/components/transcript.js
Normal file
43
www/app/components/transcript.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
const useCreateTranscript = () => {
|
||||
const [response, setResponse] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const createTranscript = () => {
|
||||
setLoading(true);
|
||||
const url = API_URL + "/v1/transcripts/";
|
||||
const data = {
|
||||
name: "Weekly All-Hands", // Hardcoded for now
|
||||
};
|
||||
|
||||
console.log("Sending POST:", data);
|
||||
|
||||
axios
|
||||
.post(url, data)
|
||||
.then((result) => {
|
||||
setResponse(result.data);
|
||||
setLoading(false);
|
||||
console.log("Response:", result.data);
|
||||
})
|
||||
.catch((err) => {
|
||||
setError(err.response || err);
|
||||
setLoading(false);
|
||||
alert("Error: " + (err.response || err));
|
||||
console.log("Error occurred:", err.response || err); // Debugging line
|
||||
});
|
||||
};
|
||||
|
||||
// You can choose when to call createTranscript, e.g., based on some dependencies
|
||||
useEffect(() => {
|
||||
createTranscript();
|
||||
}, []); // Empty dependencies array means this effect will run once on mount
|
||||
|
||||
return { response, loading, error, createTranscript };
|
||||
};
|
||||
|
||||
export default useCreateTranscript;
|
||||
@@ -1,35 +1,41 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import Peer from "simple-peer";
|
||||
import axios from "axios";
|
||||
|
||||
// allow customization of the WebRTC server URL from env
|
||||
const WEBRTC_SERVER_URL = process.env.NEXT_PUBLIC_WEBRTC_SERVER_URL || "http://127.0.0.1:1250/offer";
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
const useWebRTC = (stream) => {
|
||||
const useWebRTC = (stream, transcript) => {
|
||||
const [data, setData] = useState({
|
||||
peer: null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!stream) {
|
||||
if (!stream || !transcript) {
|
||||
return;
|
||||
}
|
||||
const url = `${API_URL}/v1/transcripts/${transcript.id}/record/webrtc`;
|
||||
console.log("Sending RTC Offer", url, transcript);
|
||||
|
||||
let peer = new Peer({ initiator: true, stream: stream });
|
||||
|
||||
peer.on("signal", (data) => {
|
||||
if ("sdp" in data) {
|
||||
fetch(WEBRTC_SERVER_URL, {
|
||||
body: JSON.stringify({
|
||||
sdp: data.sdp,
|
||||
type: data.type,
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((answer) => peer.signal(answer))
|
||||
const rtcOffer = {
|
||||
sdp: data.sdp,
|
||||
type: data.type,
|
||||
};
|
||||
|
||||
axios
|
||||
.post(url, rtcOffer, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
const answer = response.data;
|
||||
console.log("Answer:", answer);
|
||||
peer.signal(answer);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log("Error signaling:", e);
|
||||
});
|
||||
@@ -76,7 +82,7 @@ const useWebRTC = (stream) => {
|
||||
return () => {
|
||||
peer.destroy();
|
||||
};
|
||||
}, [stream]);
|
||||
}, [stream, transcript]);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
46
www/app/components/websocket.js
Normal file
46
www/app/components/websocket.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
export const useWebSockets = (transcript_id) => {
|
||||
useEffect(() => {
|
||||
if (!transcript_id) return;
|
||||
|
||||
const url = `${process.env.NEXT_PUBLIC_WEBSOCKET_URL}/v1/transcripts/${transcript_id}/events`;
|
||||
const ws = new WebSocket(url);
|
||||
console.log("Opening websocket: ", url);
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("WebSocket connection opened");
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const message = JSON.parse(event.data);
|
||||
|
||||
switch (message.event) {
|
||||
case "TRANSCRIPT":
|
||||
if (!message.data.text) break;
|
||||
console.log("TRANSCRIPT event:", message.data.text);
|
||||
break;
|
||||
case "TOPIC":
|
||||
console.log("TOPIC event:", message.data);
|
||||
break;
|
||||
case "FINAL_SUMMARY":
|
||||
console.log("FINAL_SUMMARY event:", message.data.summary);
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown event:", message.event);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error("WebSocket error:", error);
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
console.log("WebSocket connection closed");
|
||||
};
|
||||
|
||||
return () => {
|
||||
ws.close();
|
||||
};
|
||||
}, [transcript_id]);
|
||||
};
|
||||
@@ -3,14 +3,18 @@ import React, { useState } from "react";
|
||||
import Recorder from "./components/record.js";
|
||||
import { Dashboard } from "./components/dashboard.js";
|
||||
import useWebRTC from "./components/webrtc.js";
|
||||
import useCreateTranscript from "./components/transcript.js";
|
||||
import { useWebSockets } from "./components/websocket.js";
|
||||
import "../public/button.css";
|
||||
|
||||
const App = () => {
|
||||
const [stream, setStream] = useState(null);
|
||||
|
||||
// This is where you'd send the stream and receive the data from the server.
|
||||
// transcription, summary, etc
|
||||
const serverData = useWebRTC(stream);
|
||||
const transcript = useCreateTranscript();
|
||||
const serverData = useWebRTC(stream, transcript.response);
|
||||
const webSockets = useWebSockets(transcript.response?.id);
|
||||
|
||||
console.log("serverData", serverData);
|
||||
|
||||
const sendStopCmd = () =>
|
||||
serverData?.peer?.send(JSON.stringify({ cmd: "STOP" }));
|
||||
|
||||
Reference in New Issue
Block a user