-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Introduce livekit to the project. - Create livekit webhook implementation. - Link it with API Key and URL. - Test it on OBS. - Implement live streaming. - Create video component and dependency components for it. - Add video component to stream player. - Create custom controls for video. - Create full screen control, live-video, loading-video, offline-video, volume-control. Users can now connect to their favorite streaming/recording software and go live on S3MER platform.
- Loading branch information
1 parent
2e20670
commit 09e988f
Showing
17 changed files
with
445 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
"use client"; | ||
|
||
import { Maximize, Minimize } from "lucide-react"; | ||
|
||
import Hint from "@/components/hint"; | ||
import { Button } from "../ui/button"; | ||
|
||
interface FullscreenControlProps { | ||
isFullscreen: boolean; | ||
onToggle: () => void; | ||
} | ||
|
||
const FullscreenControl = ({ | ||
isFullscreen, | ||
onToggle, | ||
}: FullscreenControlProps) => { | ||
const Icon = isFullscreen ? Minimize : Maximize; | ||
|
||
const label = isFullscreen ? "Exit fullscreen" : "Enter fullscreen"; | ||
|
||
return ( | ||
<div className="flex items-center justify-center gap-4"> | ||
<Hint | ||
label={label} | ||
asChild | ||
> | ||
<Button | ||
variant="ghost" | ||
size="icon" | ||
onClick={onToggle} | ||
className="text-primary p-1.5 hover:bg-foreground/10 rounded-lg" | ||
> | ||
<Icon className="h-5 w-5" /> | ||
</Button> | ||
</Hint> | ||
</div> | ||
); | ||
}; | ||
|
||
export default FullscreenControl; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
"use client"; | ||
|
||
import { useRef, useState, useEffect } from "react"; | ||
import { Participant, Track } from "livekit-client"; | ||
import { useTracks } from "@livekit/components-react"; | ||
import { useEventListener } from "usehooks-ts"; | ||
|
||
import VolumeControl from "./volume-control"; | ||
import FullscreenControl from "./fullscreen-control"; | ||
|
||
interface LiveVideoProps { | ||
participant: Participant; | ||
} | ||
|
||
const LiveVideo = ({ participant }: LiveVideoProps) => { | ||
const videoRef = useRef<HTMLVideoElement>(null); | ||
const wrapperRef = useRef<HTMLDivElement>(null); | ||
|
||
const [isFullscreen, setIsFullscreen] = useState(false); | ||
const [volume, setVolume] = useState(0); | ||
|
||
const onVolumeChange = (value: number) => { | ||
setVolume(+value); | ||
if (videoRef?.current) { | ||
videoRef.current.muted = value === 0; | ||
videoRef.current.volume = +value * 0.01; | ||
} | ||
}; | ||
|
||
const toggleMute = () => { | ||
const isMuted = volume === 0; | ||
|
||
setVolume(isMuted ? 50 : 0); | ||
|
||
if (videoRef?.current) { | ||
videoRef.current.muted = !isMuted; | ||
videoRef.current.volume = isMuted ? 0.5 : 0; | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
onVolumeChange(0); | ||
}, []); | ||
|
||
const toggleFullscreen = () => { | ||
if (isFullscreen) { | ||
document.exitFullscreen(); | ||
} else if (wrapperRef?.current) { | ||
wrapperRef.current.requestFullscreen(); | ||
} | ||
}; | ||
|
||
const handleFullscreenChange = () => { | ||
const isCurrentlyFullscreen = document.fullscreenElement !== null; | ||
setIsFullscreen(isCurrentlyFullscreen); | ||
}; | ||
|
||
useEventListener("fullscreenchange", handleFullscreenChange, wrapperRef); | ||
|
||
useTracks([Track.Source.Camera, Track.Source.Microphone]) | ||
.filter((track) => track.participant.identity === participant.identity) | ||
.forEach((track) => { | ||
if (videoRef.current) { | ||
track.publication.track?.attach(videoRef.current); | ||
} | ||
}); | ||
|
||
return ( | ||
<div | ||
ref={wrapperRef} | ||
className="relative h-full flex" | ||
> | ||
<video | ||
ref={videoRef} | ||
width="100%" | ||
/> | ||
<div className="absolute top-0 h-full w-full opacity-0 hover:opacity-100 hover:transition-all"> | ||
<div className="absolute bottom-0 flex h-10 w-full items-center justify-between bg-background/70 px-4"> | ||
<VolumeControl | ||
onChange={onVolumeChange} | ||
value={volume} | ||
onToggle={toggleMute} | ||
/> | ||
<FullscreenControl | ||
isFullscreen={isFullscreen} | ||
onToggle={toggleFullscreen} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default LiveVideo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Loader } from "lucide-react"; | ||
|
||
interface LoadingVideoProps { | ||
label: string; | ||
} | ||
|
||
const LoadingVideo = ({ label }: LoadingVideoProps) => { | ||
return ( | ||
<div className="h-full flex flex-col space-y-4 justify-center items-center"> | ||
<Loader className="h-10 w-10 text-muted-foreground animate-spin" /> | ||
<p className="text-muted-foreground capitalize">{label}</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export default LoadingVideo; |
Oops, something went wrong.