Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: stream timer and stream stability #691

Merged
merged 1 commit into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/lib/WHEPClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,19 @@ export default class WHEPClient extends EventTarget {
console.log('got unknown track ' + track)
}

if (trackType === 'screen' && track.readyState === 'live') {
this.dispatchEvent(new CustomEvent(`isScreenLive`, { detail: true }))
if (trackType === 'screen' && track.kind === 'video') {
if (track.readyState === 'live') {
this.dispatchEvent(new CustomEvent(`isScreenLive`, { detail: true }))
} else {
this.dispatchEvent(new CustomEvent(`isScreenLive`, { detail: false }))
}
}
if (trackType === 'webcam' && track.readyState === 'live') {
this.dispatchEvent(new CustomEvent(`isWebcamLive`, { detail: true }))
if (trackType === 'webcam' && track.kind === 'video') {
if (track.readyState === 'live') {
this.dispatchEvent(new CustomEvent(`isWebcamLive`, { detail: true }))
} else {
this.dispatchEvent(new CustomEvent(`isWebcamLive`, { detail: false }))
}
}
}

Expand Down
15 changes: 10 additions & 5 deletions src/lib/components/Channel/Stream/StreamContainer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import { createEventDispatcher } from 'svelte'
import { is_sharing_audio, is_sharing_screen, is_sharing_webcam } from '$lib/stores/streamStore'

const dispatch = createEventDispatcher()
export let userCount: number = 1,
channel: any,
channels: any = [],
isHostOrGuest: boolean = false,
viewers: any[] = [],
streamId: any
viewers: any[] = []

let isScrollable = false

Expand All @@ -33,7 +33,8 @@
goto(`${id}`, {
keepFocus: true,
replaceState: true,
noScroll: true
noScroll: true,
invalidateAll: true
})
}
}
Expand All @@ -44,7 +45,11 @@

<div class="flex justify-center h-full">
<div
class="carousel carousel-vertical rounded-lg bg-base-100 w-full m-5 mb-24 {isScrollable
class="carousel carousel-vertical rounded-lg bg-base-100 w-full m-5 mb-24 {isScrollable ||
$is_sharing_audio ||
$is_sharing_screen ||
$is_sharing_webcam ||
$is_sharing_audio
? 'overflow-y-hidden'
: ''}">
{#each channels as nextchannel}
Expand All @@ -70,7 +75,7 @@
</div>
</div>
{#if channel && nextchannel?._id === $page.params.channelId}
<VideoGrid bind:streamId bind:channel />
<VideoGrid bind:channel />
{/if}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/Channel/Stream/VideoGrid.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { getVideoGrids } from '$lib/utils'
import CommandList from '$lib/components/Channel/Stream/CommandList.svelte'

export let channel: any, streamId: any
export let channel: any

$: grid = getVideoGrids(channel.videoItems, 9)
</script>
Expand All @@ -15,7 +15,7 @@
{#each grid as row}
<div class="flex flex-row gap-4 justify-center h-full">
{#each row as video (video._id)}
<VideoItem bind:streamId bind:video {channel} />
<VideoItem bind:video {channel} />
{/each}
</div>
{/each}
Expand Down
126 changes: 62 additions & 64 deletions src/lib/components/Channel/Stream/VideoItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import { addScreen, getScreen, removeScreen } from '$lib/stream-utils'
import IconDrawerVerification from '$lib/assets/icons/drawer/IconDrawerVerification.svelte'
import { Player, DefaultUi, Hls } from '@vime/svelte'
import { get, patch, post, put } from '$lib/api'
import { get, patch } from '$lib/api'

export let streamId: any, video: any, channel: any
export let video: any, channel: any

let role = '',
coloredRole: any = {},
Expand Down Expand Up @@ -49,7 +49,8 @@
obs_modal: any = null,
player: any,
hlsUrl: string = '',
hasActiveObsStream = false
hasActiveObsStream = false,
streamId = ''

// WHIP/WHEP variables that determine if stream is coming in
$: isScreenLive = false
Expand Down Expand Up @@ -90,8 +91,10 @@
handleAudioChanges()
}

$: if ($is_feature_stats_enabled && (isScreenLive || isWebcamLive || hasActiveObsStream)) {
toggleTimer()
$: if ($is_feature_stats_enabled && (isScreenLive || hasActiveObsStream)) {
toggleTimer(true)
} else {
toggleTimer(false)
}

$: animate = isWebcamFocused ? '' : 'transition-all'
Expand Down Expand Up @@ -130,25 +133,6 @@
break
case 'screen':
if (video.screen && $is_sharing_screen) {
if (streamId == '') {
const streamData = await post(
'stats/stream',
{
type: 'stream',
userId: $page.data.user?.userId,
user: $page.data.user,
start: Date.now(),
end: 0,
duration: 0
},
{
userId: $page.data.user?.userId,
token: $page.data.user?.token
}
)
streamId = streamData.insertedId
}

const key = video.screen.webRTC.url + '-' + video._id
const existed = getScreen(key)
screenWhip =
Expand All @@ -165,17 +149,6 @@
$is_sharing_screen = false
isScreenLive = false
removeScreen(key)
if (streamId) {
await patch(
`stats/stream/end?streamId=${streamId}`,
{},
{
userId: $page.data.user?.userId,
token: $page.data.user?.token
}
)
streamId = ''
}
})
screenWhip.addEventListener(`isScreenLive`, (ev: any) => (isScreenLive = ev.detail))
} else if (!video.screen) {
Expand All @@ -202,6 +175,8 @@
if (webcamElement) {
webcamElement.srcObject = null
}
$is_sharing_webcam = false
isWebcamLive = false
}
break
case 'audio':
Expand Down Expand Up @@ -233,15 +208,11 @@
if (existed) {
existed.videoElement = screenElement
screenElement.srcObject = existed.stream
isScreenLive = true
const streamRecord = await get(`stats/stream?streamId=${streamId}`)
streamTime = streamRecord ? (Date.now() - streamRecord.start) / 1000 : 0
toggleTimer()
isScreenLive = true //TODO: fixes scrolling to new stream, but breaks when host ends stream
screenElement.muted = false
screenElement.play()
}

addScreen(key, screenWhep)
screenElement.muted = false
screenElement.play()
screenWhep.addEventListener(`isScreenLive`, (ev: any) => (isScreenLive = ev.detail))
} else {
if (screenElement) screenElement.srcObject = null
Expand Down Expand Up @@ -291,6 +262,7 @@
}

onMount(() => {
toggleTimer(false)
isGuest = channel?.guests?.includes(video._id)
handleObsChanges()

Expand Down Expand Up @@ -334,7 +306,18 @@
is_sharing_screen.subscribe(async (value: any) => {
if (value === false) {
screenWhip?.disconnectStream()
clearInterval(timerInterval)
toggleTimer(false)
if (streamId) {
await patch(
`stats/stream/end?streamId=${streamId}`,
{},
{
userId: $page.data.user?.userId,
token: $page.data.user?.token
}
)
streamId = ''
}
}
})

Expand Down Expand Up @@ -398,29 +381,44 @@
})
}

const toggleTimer = () => {
if (timerInterval) {
const toggleTimer = (isTimerEnabled: boolean) => {
if (!isTimerEnabled) {
clearInterval(timerInterval)
timerInterval = null
streamTime = 0
formattedTime = '00:00:00'
streamId = ''
} else {
if (timerInterval) return
timerInterval = setInterval(async () => {
streamTime++
const hours = Math.floor(streamTime / 3600)
const minutes = Math.floor((streamTime % 3600) / 60)
const seconds = streamTime % 60
formattedTime = `${hours.toString().padStart(2, '0')}:${minutes
.toString()
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
//NOTE: check if mine and has been 5 seconds
if (video._id === $page.data.user?.userId && streamTime % 5 == 0) {
await patch(
`stats/stream?streamId=${streamId}`,
{},
{
userId: $page.data.user?.userId,
token: $page.data.user?.token
}
)
try {
streamId = video.screen.streamId
if (!streamId) return
console.log('got here----', video.screen.streamId)
if (streamId && streamTime === 0) {
const streamRecord = await get(`stats/stream?streamId=${streamId}`)
streamTime = streamRecord ? (Date.now() - streamRecord.start) / 1000 : 0
}
streamTime = Math.floor(streamTime) + 1
const hours = Math.floor(streamTime / 3600)
const minutes = Math.floor((streamTime % 3600) / 60)
const seconds = streamTime % 60
formattedTime = `${hours.toString().padStart(2, '0')}:${minutes
.toString()
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
//NOTE: check if mine and has been 5 seconds
if (video._id === $page.data.user?.userId && streamTime % 5 == 0) {
await patch(
`stats/stream?streamId=${streamId}`,
{},
{
userId: $page.data.user?.userId,
token: $page.data.user?.token
}
)
}
} catch (e) {
console.log(e)
}
}, 1000)
}
Expand Down Expand Up @@ -448,7 +446,7 @@
<div class="absolute inset-0">
{#if $is_feature_stats_enabled && (isScreenLive || isWebcamLive || hasActiveObsStream)}
<span
class="btn btn-sm btn-neutral font-medium text-white border-none items-center w-fit absolute top-2 left-2 {isHoverVideo
class="z-10 btn btn-sm btn-neutral font-medium text-white border-none items-center w-fit absolute top-2 left-2 {isHoverVideo
? 'opacity-100'
: 'opacity-50'}">
{formattedTime}
Expand Down Expand Up @@ -492,7 +490,7 @@
muted
class="rounded-md h-full w-full" />
</div>
<video bind:this={audioElement} autoplay muted class="rounded-md w-0 h-0" />
<video bind:this={audioElement} autoplay class="rounded-md w-0 h-0" />
<div class="absolute left-2 bottom-2 rounded-md dropdown">
<label
tabindex="0"
Expand Down
14 changes: 7 additions & 7 deletions src/lib/stream-utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
var aliveScreens:any = {}
const aliveScreens: any = {}

export const addScreen = (key:string, screen:any) => {
aliveScreens[key] = screen
export const addScreen = (key: string, screen: any) => {
aliveScreens[key] = screen
}

export const getScreen = (key:string):any => {
return aliveScreens[key]
export const getScreen = (key: string): any => {
return aliveScreens[key]
}

export const removeScreen = (key:string) => {
delete aliveScreens[key]
export const removeScreen = (key: string) => {
delete aliveScreens[key]
}
17 changes: 2 additions & 15 deletions src/routes/channel/[channelId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
skip = 0,
limit = 10,
viewers: any[] = [],
chatHistory: any[] = [],
streamId = ''
chatHistory: any[] = []

$: userCount = 0
$: isHostOrGuest =
Expand Down Expand Up @@ -83,17 +82,6 @@
if ($is_sharing_screen) $is_sharing_screen = false
if ($is_sharing_webcam) $is_sharing_webcam = false
if ($is_sharing_audio) $is_sharing_audio = false
if (streamId) {
await patch(
`stats/stream/end?streamId=${streamId}`,
{},
{
userId: $page.data.user?.userId,
token: $page.data.user?.token
}
)
streamId = ''
}
} else {
$is_sharing_screen = undefined
$is_sharing_webcam = undefined
Expand Down Expand Up @@ -320,8 +308,7 @@
bind:channels
on:loadMore={loadMoreChannels}
bind:isHostOrGuest
bind:viewers
bind:streamId />
bind:viewers />

{#if showEditChannelDrawer}
<DrawerEditChannel bind:channel bind:showDrawer={showEditChannelDrawer} />
Expand Down