mirror of
https://github.com/DerTyp7/teamspeak-obs-overlay.git
synced 2026-07-31 16:49:04 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f296bba7d6 | ||
|
|
268252bf56 | ||
|
|
b7beddb32e | ||
|
|
92906d25c3 | ||
|
|
1bd6e3400b | ||
|
|
7d2409f6f4 | ||
|
|
b702b82cce | ||
|
|
00b8db20c3 | ||
|
|
16573394b1 | ||
|
|
08fa223207 | ||
|
|
e2423a54cf |
58
README.md
Normal file
58
README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Teamspeak5-OBS-Overlay
|
||||
|
||||
This is a overlay for OBS to show the current talking clients in your Teamspeak 5 Channel.
|
||||
This App uses the new "Remote Apps" feature of Teamspeak 5.
|
||||
|
||||

|
||||
|
||||
- [Teamspeak5-OBS-Overlay](#teamspeak5-obs-overlay)
|
||||
- [Setup](#setup)
|
||||
- [Customization (Parameters)](#customization-parameters)
|
||||
- [Setup (Developer)](#setup-developer)
|
||||
|
||||
## Setup
|
||||
|
||||
1. Download the `index.html` of the latest release from [here](https://github.com/DerTyp876/ts5-obs-overlay/releases/tag/v1.0.0)
|
||||

|
||||
1.1. (optional) You can rename the file. Just remember using the new file name in the future instead of `index.html`
|
||||
2. Go into the Teamspeak 5 Settings and enable "Remote Apps"
|
||||

|
||||
|
||||
3. Add a new Browser Source to your OBS Scene
|
||||

|
||||

|
||||
|
||||
4. Tick the checkbox "Local File" and select the downloaded `index.html`
|
||||
4.1. Set the width and height to your desired size (e.g. 1920x1080 OR 1280x720)
|
||||

|
||||
|
||||
5. You should now receive a notification in Teamspeak 5 that the app is allowed to connect to your Teamspeak 5 client. Allow it. (If you don't get a notification, restart Teamspeak 5 and OBS -> try again)
|
||||

|
||||
|
||||
### Customization (Parameters)
|
||||
|
||||
You can customize the overlay by adding parameters to the URL of the Browser Source.
|
||||
|
||||
1. Open your Browser Source settings
|
||||
2. **Untick** the checkbox "Local File"
|
||||
3. Add `file://` to the beginning of the URL
|
||||

|
||||
4. Start adding parameters like discribed below
|
||||
|
||||
Start by adding a `?` to the end of the URL and then add the parameters.
|
||||
To add multiple parameters, you have to seperate them with a `&`.
|
||||
|
||||
Like this: `file://C:/Users/.../index.html?parameter1=value1¶meter2=value2`
|
||||
Real example: `file://C:/Users/.../index.html?remoteAppPort=5899`
|
||||
|
||||
This is a list of all available parameters (all parameters are optional):
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| --------------- | -------------------------------------- | ------- |
|
||||
| `remoteAppPort` | The port of the Teamspeak 5 remote app | `5899` |
|
||||
|
||||
## Setup (Developer)
|
||||
|
||||
1. Clone this repository
|
||||
2. Run `npm install`
|
||||
3. To start the development server run `npm run dev`
|
||||
39
package-lock.json
generated
39
package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.14.0",
|
||||
"sass": "^1.62.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -502,6 +503,14 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.0.tgz",
|
||||
"integrity": "sha512-Eu1V3kz3mV0wUpVTiFHuaT8UD1gj/0VnoFHQYX35xlslQUpe8CuYoKFn9d4WZFHm3yDywz6ALZuGdnUPKrNeAw==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.3.62",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.62.tgz",
|
||||
@@ -2171,6 +2180,36 @@
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.0.tgz",
|
||||
"integrity": "sha512-OD+vkrcGbvlwkspUFDgMzsu1RXwdjNh83YgG/28lBnDzgslhCgxIqoExLlxsfTpIygp7fc+Hd3esloNwzkm2xA==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.0.tgz",
|
||||
"integrity": "sha512-YEwlApKwzMMMbGbhh+Q7MsloTldcwMgHxUY/1g0uA62+B1hZo2jsybCWIDCL8zvIDB1FA0pBKY9chHbZHt+2dQ==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.7.0",
|
||||
"react-router": "6.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.14.0",
|
||||
"sass": "^1.62.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -4,8 +4,11 @@ import { TS5Connection } from "./teamspeak5Handler";
|
||||
import { IChannel, IClient, IConnection } from "interfaces/teamspeak";
|
||||
import { useEffect, useState } from "react";
|
||||
import Viewer from "./Viewer";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
|
||||
export default function App() {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const [clients, setClients] = useState<IClient[]>([]);
|
||||
const [channels, setChannels] = useState<IChannel[]>([]);
|
||||
const [connections, setConnections] = useState<IConnection[]>([]);
|
||||
@@ -33,8 +36,10 @@ export default function App() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const remoteAppPort = searchParams.get("remoteAppPort");
|
||||
|
||||
const tsConnection: TS5Connection = new TS5Connection(
|
||||
5899,
|
||||
parseInt(remoteAppPort ?? "5899"),
|
||||
setConnections,
|
||||
setChannels,
|
||||
setClients,
|
||||
@@ -52,7 +57,7 @@ export default function App() {
|
||||
<Viewer
|
||||
clients={
|
||||
clients.map((client) => {
|
||||
if (client.channel?.id === currentChannel?.id) {
|
||||
if (client.channel?.id === currentChannel?.id && client.channel.connection.id === activeConnectionId) {
|
||||
return client;
|
||||
}
|
||||
}) as IClient[]
|
||||
|
||||
@@ -72,7 +72,7 @@ export default function Viewer({
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <></>;
|
||||
return <div key={Math.random()}></div>;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./App.tsx";
|
||||
import "@styles/index.scss";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ export class TS5Connection {
|
||||
setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>,
|
||||
setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>,
|
||||
setClients: React.Dispatch<React.SetStateAction<IClient[]>>,
|
||||
setActiveConnectionId: React.Dispatch<React.SetStateAction<number>>,
|
||||
setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>,
|
||||
) {
|
||||
// Create websocket connection to TS5 client
|
||||
this.remoteAppPort = remoteAppPort;
|
||||
@@ -26,10 +26,11 @@ export class TS5Connection {
|
||||
|
||||
// Create dataHandler and messageHandler
|
||||
this.dataHandler = new TS5DataHandler(setConnections, setChannels, setClients);
|
||||
this.messageHandler = new TS5MessageHandler(this.ws, this.dataHandler, setActiveConnectionId);
|
||||
this.messageHandler = new TS5MessageHandler(this.ws, this.dataHandler, setActiveConnectionStateId);
|
||||
}
|
||||
|
||||
reconnect() {
|
||||
console.log("Reconnecting...")
|
||||
this.ws.close();
|
||||
|
||||
this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`);
|
||||
@@ -74,7 +75,9 @@ export class TS5Connection {
|
||||
localStorage.removeItem("apiKey");
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.reconnect();
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
// Handle messages received from TS5 client
|
||||
@@ -325,12 +328,18 @@ class TS5MessageHandler {
|
||||
ws: WebSocket;
|
||||
dataHandler: TS5DataHandler;
|
||||
|
||||
setActiveConnectionId: React.Dispatch<React.SetStateAction<number>>;
|
||||
setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>;
|
||||
activeConnectionId = 0;
|
||||
|
||||
constructor(ws: WebSocket, dataHandler: TS5DataHandler, setActiveConnectionId: React.Dispatch<React.SetStateAction<number>>) {
|
||||
constructor(ws: WebSocket, dataHandler: TS5DataHandler, setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>) {
|
||||
this.ws = ws;
|
||||
this.dataHandler = dataHandler;
|
||||
this.setActiveConnectionId = setActiveConnectionId;
|
||||
this.setActiveConnectionStateId = setActiveConnectionStateId;
|
||||
}
|
||||
|
||||
setActiveConnection(connectionId: number) {
|
||||
this.activeConnectionId = connectionId;
|
||||
this.setActiveConnectionStateId(connectionId);
|
||||
}
|
||||
|
||||
parseChannelInfos(channelInfos: IChannelInfos, connection: IConnection) {
|
||||
@@ -473,8 +482,10 @@ class TS5MessageHandler {
|
||||
handleClientSelfPropertyUpdatedMessage(data: IClientSelfPropertyUpdatedMessage) {
|
||||
console.log("handleClientSelfPropertyUpdated", data);
|
||||
|
||||
if (data.payload.flag == "inputHardware") { // sadly thats the only way to detect if a server is active or not
|
||||
this.setActiveConnectionId(data.payload.connectionId);
|
||||
const connection: IConnection | undefined = this.dataHandler.getConnectionById(this.activeConnectionId);
|
||||
|
||||
if (data.payload.flag == "inputHardware" || connection == undefined) { // sadly thats the only way to detect if a server is active or not
|
||||
this.setActiveConnection(data.payload.connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user