Spaces:
Running
Running
Commit
โข
e423758
1
Parent(s):
733cce1
go HD by default
Browse files- public/index.html +60 -24
- src/index.mts +16 -0
public/index.html
CHANGED
@@ -21,36 +21,46 @@
|
|
21 |
class="fixed w-full z-20 py-4 px-6 top-0 font-mono text-white flex items-center justify-between space-x-1 bg-black bg-opacity-60"
|
22 |
style="text-shadow: 0px 0px 3px #000000">
|
23 |
|
24 |
-
<div class="text-
|
|
|
|
|
25 |
<template x-for="chan in channels">
|
26 |
-
<
|
27 |
-
class="text-
|
28 |
:class="chan.id === channel.id
|
29 |
? 'font-bold'
|
30 |
: 'hover:underline opacity-60 hover:opacity-80 cursor-pointer'"
|
31 |
x-on:click="window.location = `${window.location.origin}/?channel=${chan.id}&beta=true`"
|
32 |
-
x-text="chan.label"></
|
33 |
</template>
|
34 |
</div>
|
35 |
|
36 |
-
<div class="flex justify-between space-x-
|
37 |
-
|
38 |
-
class="
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
<div
|
47 |
x-on:click="toggleAudio()"
|
48 |
class="flex items-center justify-center text-white opacity-80 hover:opacity-100 cursor-pointer">
|
49 |
<div x-show="muted">
|
50 |
-
<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="
|
51 |
</div>
|
52 |
<div x-show="!muted">
|
53 |
-
<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 512" width="
|
54 |
</div>
|
55 |
</div>
|
56 |
<div
|
@@ -81,20 +91,24 @@ function app() {
|
|
81 |
return {
|
82 |
enabled: false,
|
83 |
channels: {
|
84 |
-
|
85 |
-
id: '
|
86 |
label: '#legacy',
|
87 |
-
|
|
|
|
|
88 |
resolution: '576x320',
|
89 |
-
model: '
|
90 |
modelUrl: 'https://huggingface.co/cerspense/zeroscope_v2_576w',
|
91 |
},
|
92 |
-
|
93 |
-
id: '
|
94 |
label: '#HDTV',
|
95 |
-
|
|
|
|
|
96 |
resolution: '1024x576',
|
97 |
-
model: '
|
98 |
modelUrl: 'https://huggingface.co/cerspense/zeroscope_v2_XL',
|
99 |
},
|
100 |
},
|
@@ -102,7 +116,7 @@ function app() {
|
|
102 |
muted: true,
|
103 |
initialized: false,
|
104 |
activityTimeout: null,
|
105 |
-
defaultChannelId: '
|
106 |
video: null,
|
107 |
channel: {
|
108 |
},
|
@@ -122,6 +136,24 @@ function app() {
|
|
122 |
this.muted = true
|
123 |
}
|
124 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
fullscreen() {
|
126 |
if (this.video.requestFullscreen) {
|
127 |
this.video.requestFullscreen();
|
@@ -172,6 +204,10 @@ function app() {
|
|
172 |
document.addEventListener("click", handleActivity)
|
173 |
document.addEventListener("mousemove", handleActivity)
|
174 |
|
|
|
|
|
|
|
|
|
175 |
// detect mute/unmute events
|
176 |
this.video.addEventListener("mute", () => {
|
177 |
this.muted = true
|
|
|
21 |
class="fixed w-full z-20 py-4 px-6 top-0 font-mono text-white flex items-center justify-between space-x-1 bg-black bg-opacity-60"
|
22 |
style="text-shadow: 0px 0px 3px #000000">
|
23 |
|
24 |
+
<div class="flex text-xl space-x-2">
|
25 |
+
<div class="text-xl">๐ค AI WebTV</div>
|
26 |
+
<div class="text-md">๐ Pick a stream:</div>
|
27 |
<template x-for="chan in channels">
|
28 |
+
<div
|
29 |
+
class="text-xl mr-2"
|
30 |
:class="chan.id === channel.id
|
31 |
? 'font-bold'
|
32 |
: 'hover:underline opacity-60 hover:opacity-80 cursor-pointer'"
|
33 |
x-on:click="window.location = `${window.location.origin}/?channel=${chan.id}&beta=true`"
|
34 |
+
x-text="chan.label"></div>
|
35 |
</template>
|
36 |
</div>
|
37 |
|
38 |
+
<div class="flex justify-between space-x-6 items-center">
|
39 |
+
|
40 |
+
<div class="flex items-center justify-center text-white opacity-100 space-x-2">
|
41 |
+
<div>
|
42 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 640 512"><path fill="currentColor" d="M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM609.3 512H471.4c5.4-9.4 8.6-20.3 8.6-32v-8c0-60.7-27.1-115.2-69.8-151.8c2.4-.1 4.7-.2 7.1-.2h61.4C567.8 320 640 392.2 640 481.3c0 17-13.8 30.7-30.7 30.7zM432 256c-31 0-59-12.6-79.3-32.9C372.4 196.5 384 163.6 384 128c0-26.8-6.6-52.1-18.3-74.3C384.3 40.1 407.2 32 432 32c61.9 0 112 50.1 112 112s-50.1 112-112 112z"/></svg>
|
43 |
+
</div>
|
44 |
+
<div x-text="channel.audience"></div>
|
45 |
+
</div>
|
46 |
+
|
47 |
+
<div class="text-sm">(<a
|
48 |
+
class="hover:underline"
|
49 |
+
href="https://huggingface.co/facebook/musicgen-melody"
|
50 |
+
target="_blank">musicgen-melody</a> + <a
|
51 |
+
class="hover:underline"
|
52 |
+
:href="channel.modelUrl"
|
53 |
+
x-text="channel.model"
|
54 |
+
target="_blank"></a>)</div>
|
55 |
|
56 |
<div
|
57 |
x-on:click="toggleAudio()"
|
58 |
class="flex items-center justify-center text-white opacity-80 hover:opacity-100 cursor-pointer">
|
59 |
<div x-show="muted">
|
60 |
+
<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="32px" height="32px"><path fill="currentColor" d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zM461.64 256l45.64-45.64c6.3-6.3 6.3-16.52 0-22.82l-22.82-22.82c-6.3-6.3-16.52-6.3-22.82 0L416 210.36l-45.64-45.64c-6.3-6.3-16.52-6.3-22.82 0l-22.82 22.82c-6.3 6.3-6.3 16.52 0 22.82L370.36 256l-45.63 45.63c-6.3 6.3-6.3 16.52 0 22.82l22.82 22.82c6.3 6.3 16.52 6.3 22.82 0L416 301.64l45.64 45.64c6.3 6.3 16.52 6.3 22.82 0l22.82-22.82c6.3-6.3 6.3-16.52 0-22.82L461.64 256z" class=""></path></svg>
|
61 |
</div>
|
62 |
<div x-show="!muted">
|
63 |
+
<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 512" width="32px" height="32px"><path fill="currentColor" d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zM480 256c0-63.53-32.06-121.94-85.77-156.24-11.19-7.14-26.03-3.82-33.12 7.46s-3.78 26.21 7.41 33.36C408.27 165.97 432 209.11 432 256s-23.73 90.03-63.48 115.42c-11.19 7.14-14.5 22.07-7.41 33.36 6.51 10.36 21.12 15.14 33.12 7.46C447.94 377.94 480 319.53 480 256zm-141.77-76.87c-11.58-6.33-26.19-2.16-32.61 9.45-6.39 11.61-2.16 26.2 9.45 32.61C327.98 228.28 336 241.63 336 256c0 14.38-8.02 27.72-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.86z" class=""></path></svg>
|
64 |
</div>
|
65 |
</div>
|
66 |
<div
|
|
|
91 |
return {
|
92 |
enabled: false,
|
93 |
channels: {
|
94 |
+
legacy: {
|
95 |
+
id: 'legacy',
|
96 |
label: '#legacy',
|
97 |
+
audience: 0,
|
98 |
+
online: false,
|
99 |
+
url: 'https://jbilcke-hf-media-server.hf.space/live/legacy.flv',
|
100 |
resolution: '576x320',
|
101 |
+
model: 'zeroscope_v2_576w',
|
102 |
modelUrl: 'https://huggingface.co/cerspense/zeroscope_v2_576w',
|
103 |
},
|
104 |
+
hdtv: {
|
105 |
+
id: 'hdtv',
|
106 |
label: '#HDTV',
|
107 |
+
audience: 0,
|
108 |
+
online: false,
|
109 |
+
url: 'https://jbilcke-hf-media-server.hf.space/live/hdtv.flv',
|
110 |
resolution: '1024x576',
|
111 |
+
model: 'zeroscope_v2_XL',
|
112 |
modelUrl: 'https://huggingface.co/cerspense/zeroscope_v2_XL',
|
113 |
},
|
114 |
},
|
|
|
116 |
muted: true,
|
117 |
initialized: false,
|
118 |
activityTimeout: null,
|
119 |
+
defaultChannelId: 'hdtv',
|
120 |
video: null,
|
121 |
channel: {
|
122 |
},
|
|
|
136 |
this.muted = true
|
137 |
}
|
138 |
},
|
139 |
+
async checkAudience() {
|
140 |
+
let audience = {}
|
141 |
+
try {
|
142 |
+
const res = await fetch('/stats')
|
143 |
+
audience = await res.json()
|
144 |
+
} catch (err) {
|
145 |
+
console.log('failed to check the audience, something is wrong')
|
146 |
+
}
|
147 |
+
console.log('audience:', audience)
|
148 |
+
|
149 |
+
this.channels = Object.entries(this.channels).reduce((acc, [channel, data]) => ({
|
150 |
+
...acc,
|
151 |
+
[channel]: {
|
152 |
+
...data,
|
153 |
+
audience: audience[channel] || 0
|
154 |
+
}
|
155 |
+
}))
|
156 |
+
},
|
157 |
fullscreen() {
|
158 |
if (this.video.requestFullscreen) {
|
159 |
this.video.requestFullscreen();
|
|
|
204 |
document.addEventListener("click", handleActivity)
|
205 |
document.addEventListener("mousemove", handleActivity)
|
206 |
|
207 |
+
setInterval(() => {
|
208 |
+
this.checkAudience()
|
209 |
+
}, 2000)
|
210 |
+
|
211 |
// detect mute/unmute events
|
212 |
this.video.addEventListener("mute", () => {
|
213 |
this.muted = true
|
src/index.mts
CHANGED
@@ -5,4 +5,20 @@ const port = 7860
|
|
5 |
|
6 |
app.use(express.static('public'))
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
app.listen(port, () => { console.log(`Open http://localhost:${port}`) })
|
|
|
5 |
|
6 |
app.use(express.static('public'))
|
7 |
|
8 |
+
app.get('/stats', async (req, res) => {
|
9 |
+
try {
|
10 |
+
const results = await fetch(process.env.WEBTV_MEDIA_SERVER_API_URL)
|
11 |
+
const json = await results.json()
|
12 |
+
const response = Object.entries(json.live).reduce((acc, [key, channel]) => ({
|
13 |
+
...acc,
|
14 |
+
[key]: (channel as any).subscribers.length
|
15 |
+
}), {})
|
16 |
+
res.write(JSON.stringify(response))
|
17 |
+
res.end()
|
18 |
+
} catch (err) {
|
19 |
+
res.write(JSON.stringify({}))
|
20 |
+
res.end()
|
21 |
+
}
|
22 |
+
})
|
23 |
+
|
24 |
app.listen(port, () => { console.log(`Open http://localhost:${port}`) })
|