Skip to content

Commit

Permalink
Detect active camera
Browse files Browse the repository at this point in the history
  • Loading branch information
computer committed Jan 26, 2024
1 parent b3743d5 commit b3c7df5
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 46 deletions.
2 changes: 0 additions & 2 deletions Backend/.env-openvidu
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
OPENVIDU_SECRET=MY_SECRET
OPENVIDU_WEBHOOK=true
OPENVIDU_WEBHOOK_ENDPOINT=https://localhost:8080/media-server
1 change: 0 additions & 1 deletion Backend/src/app/mediaServer/mediaServer.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class MediaServerController {
@Header('Content-Type', 'application/json')
@Post('/media-server')
async getMediaServerEvents(@Body() event: any) {
console.log(event);
this.cameraStreamGateway.broadcastEvent(event);
return { message: 'OK' };
}
Expand Down
31 changes: 24 additions & 7 deletions Backend/src/cameraStream/cameraStream.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,18 @@ export class CameraStreamGateway implements OnGatewayConnection {

async afterInit() {
try {
const session = await this.openvidu.instance.createSession({});
const session = await this.openvidu.instance.createSession();
this.sessionId = session.sessionId;

const nvr = await this.database.getNVRData();
nvr.channels.forEach((id: number) => {

[{rtsp:"rtsp://192.168.129.244:554",id:"0"},{rtsp:"rtsp://192.168.129.234:554",id:"1"}].forEach((item) => {
const connectionProperties: ConnectionProperties = {
type: ConnectionType.IPCAM,
rtspUri: `${nvr.ip}/ch${id}_0.264`,
rtspUri: item.rtsp,
adaptativeBitrate: true,
onlyPlayWithSubscribers: false,
onlyPlayWithSubscribers: true,
networkCache: 1000,
data: id.toString(),
data: item.id,
};
console.log(connectionProperties);

Expand All @@ -76,8 +76,25 @@ export class CameraStreamGateway implements OnGatewayConnection {
.then((connection: unknown) => console.log(connection))
.catch((error) => console.error(error));
});

// nvr.channels.forEach((id: number) => {
// const connectionProperties: ConnectionProperties = {
// type: ConnectionType.IPCAM,
// rtspUri: `${nvr.ip}/ch${id}_0.264`,
// adaptativeBitrate: true,
// onlyPlayWithSubscribers: true,
// networkCache: 1000,
// data: id.toString(),
// };
// console.log(connectionProperties);

// session
// .createConnection(connectionProperties)
// .then((connection: unknown) => console.log(connection))
// .catch((error) => console.error(error));
// });
} catch (error) {
console.error(`OpenVidu initialization Failed...`);
console.error(error);
}
}

Expand Down
4 changes: 2 additions & 2 deletions Backend/src/database/database.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,10 @@ export class DatabaseService {
const array = await this.getRawDataArray('General', {
name: 'NVR',
});

return {
ip: process.env.NVR_IP_ADDRESS,
channels: array[0].channels,
channels: cameraIds,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ const VideoPlayer = ({
}) => {
const [fullScreen, setFullScreen] = useState(false);
const [videoControlHidden, setvideoControlHidden] = useState(false);
const [loading, setLoading] = useState(true);
const intervalRef: any = useRef(null);

/* event handlers */
const onScreenSizeToggle = () => {
const elem = document.documentElement;
Expand Down Expand Up @@ -60,7 +59,6 @@ const VideoPlayer = ({

return (
<div className="w-full min-h-[250px] video-container relative">
{/* <Spin className="absolute top-1/2 left-1/2" /> */}
<video
ref={(el) => {
videoRef.current = { ...videoRef.current, [camera.id]: el };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,19 @@ export const VideoRecordingScreen: FC<PropsType> = ({ camera, videoRef }) => {
<>
{camera && (
<>
{/* {camera.isActive && (
{camera.isActive && (
<VideoPlayer camera={camera} videoRef={videoRef} />
)} */}
<VideoPlayer camera={camera} videoRef={videoRef} />
)}

{/* {!camera.isActive && (
{!camera.isActive && (
<div className="bg-black min-h-[250px] relative">
<span className="absolute animate-pulse top-1/2 left-1/2 bg-red-500 -translate-x-1/2 -translate-y-1/2 rounded-full w-8 h-8"></span>
<p className="text-white pl-2">NO SIGNAL</p>
<p className="absolute text-white text-xl top-2/3 left-1/2 -translate-x-1/2 font-bold">
{camera.name}
</p>
</div>
)} */}
)}
</>
)}

Expand Down
4 changes: 3 additions & 1 deletion Frontend/src/containers/layout-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ export const LayoutContainer = ({

useEffect(() => {
if (camerasFetchedData && session) {
setCameras(camerasFetchedData);
setCameras(
camerasFetchedData.map((item) => ({ ...item, isActive: true }))
);
}
}, [camerasFetchedData, session]);

Expand Down
55 changes: 32 additions & 23 deletions Frontend/src/containers/video-stream-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import type { FC } from "react";
import { Tooltip } from "antd";
import { VideoRecordingScreen } from "@/components";
import { useCameraSlice, useSessionSlice } from "@/hooks";
import { cameras as camerasData } from "@/data";
import { useCameraSlice } from "@/hooks";
import { FullscreenOutlined, FullscreenExitOutlined } from "@ant-design/icons";
import React, { useEffect, useRef, useState } from "react";
import { io } from "socket.io-client";
Expand All @@ -21,8 +20,12 @@ const webSocketURL = process.env.NEXT_PUBLIC_BACKEND_URL
export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
const [subscribers, setSubscribers] = useState<any[]>([]);
/* hooks */
const { cameras, isFullScreenGrid, toggleIsFullScreenGrid, setCameras } =
useCameraSlice();
const {
cameras,
isFullScreenGrid,
toggleIsFullScreenGrid,
updateCameraStatus,
} = useCameraSlice();
const videoRef: any = useRef(null);

/* event handlers */
Expand All @@ -31,13 +34,11 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
if (elem.requestFullscreen && !isFullScreenGrid) {
elem.requestFullscreen();
toggleIsFullScreenGrid(true);
console.log("Setting true");
}

if (document.exitFullscreen && isFullScreenGrid) {
document.exitFullscreen();
toggleIsFullScreenGrid(false);
console.log("Setting false");
}
};

Expand Down Expand Up @@ -94,11 +95,6 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
);
});

// On every Stream destroyed...
session.on("streamPropertyChanged", (event) => {
console.log(event);
});

// On every asynchronous exception...
session.on("exception", (exception) => {
console.error(exception);
Expand Down Expand Up @@ -141,8 +137,6 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
let publisher = await openVidu.initPublisherAsync(undefined, {
audioSource: false, // The source of audio. If undefined default microphone
videoSource: false, // The source of video. If undefined default webcam
publishAudio: false, // Whether you want to start publishing with your audio unmuted or not
publishVideo: false, // Whether you want to start publishing with your video enabled or not
});

// -Publish your stream ---
Expand Down Expand Up @@ -172,16 +166,31 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
}, []);

useEffect(() => {
subscribers.forEach((subscriber) => {
try {
subscriber.addVideoElement(
videoRef.current?.[subscriber?.stream?.connection?.data]
);
} catch (err) {
console.log(err);
}
});
}, [subscribers]);
if (cameras.length === 8) {
let toBeInActive = [...cameras];
subscribers.forEach((subscriber, index) => {
try {
subscriber.addVideoElement(
videoRef.current?.[subscriber?.stream?.connection?.data]
);
toBeInActive = toBeInActive.filter(
(item) => item.id != subscriber?.stream?.connection?.data
);
} catch (err) {
console.log(err);
}

if (index === subscribers.length - 1) {
toBeInActive.forEach((item) =>
updateCameraStatus({
id: item.id,
status: false,
})
);
}
});
}
}, [subscribers, cameras.length > 0]);

return (
<>
Expand Down
7 changes: 7 additions & 0 deletions Frontend/src/hooks/use-camera-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
updateCamera,
toggleIsFullScreenGrid,
setCameras,
updateCameraStatus,
} from "@/store";

export const useCameraSlice = () => {
Expand All @@ -31,6 +32,11 @@ export const useCameraSlice = () => {
const toggleIsFullScreenGridState = (value: boolean) => {
dispatch(toggleIsFullScreenGrid(value));
};
updateCameraStatus;

const updateCameraStatusState = (update: { id: string; status: boolean }) => {
dispatch(updateCameraStatus(update));
};

return {
cameras: cameras,
Expand All @@ -40,5 +46,6 @@ export const useCameraSlice = () => {
setCameras: setCamerasState,
updateCamera: updateCameraState,
toggleIsFullScreenGrid: toggleIsFullScreenGridState,
updateCameraStatus: updateCameraStatusState,
};
};
1 change: 1 addition & 0 deletions Frontend/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {
setCameras,
updateCamera,
toggleIsFullScreenGrid,
updateCameraStatus
} from "./slices/camera-slice";
export {
selectNotification,
Expand Down
19 changes: 17 additions & 2 deletions Frontend/src/store/slices/camera-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ export const cameraSlice = createSlice({
return item;
});
},
updateCameraStatus: (
state: CameraStateType,
action: PayloadAction<{ id: string; status: boolean }>
) => {
state.cameras = state.cameras.map((item) => {
if (item.id === action.payload.id) {
return { ...item, isActive: action.payload.status };
}
return item;
});
},
toggleIsFullScreenGrid: (
state: CameraStateType,
action: PayloadAction<boolean>
Expand All @@ -46,8 +57,12 @@ export const cameraSlice = createSlice({
},
});

export const { updateCamera, toggleIsFullScreenGrid, setCameras } =
cameraSlice.actions;
export const {
updateCamera,
toggleIsFullScreenGrid,
setCameras,
updateCameraStatus,
} = cameraSlice.actions;

// Other code such as selectors can use the imported `RootState` type
export const selectCameras = (state: RootState) => state.camera.cameras;
Expand Down

0 comments on commit b3c7df5

Please sign in to comment.