mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
Update environment variable name for Cloudflare live input UID and refactor StreamPage to fetch HLS URL from API
- Rename `CLOUDFLARE_STREAM_NIKIV_VIDEO_ID` to `CLOUDFLARE_LIVE_INPUT_UID` in env.d.ts - Remove hardcoded `LIVE_INPUT_UID` constant from `$username.tsx` - Add `hlsUrl` state and update it based on API response in `$username.tsx` - Modify stream playback logic to use `hlsUrl` for nikiv user - Fetch HLS URL from server-side API and update state accordingly - Update `check-hls.ts` to derive HLS URL dynamically from environment variables - Remove `CLOUDFLARE_LIVE_INPUT_UID` from `wrangler.jsonc` environment variables
This commit is contained in:
2
packages/web/src/env.d.ts
vendored
2
packages/web/src/env.d.ts
vendored
@@ -13,7 +13,7 @@ declare namespace Cloudflare {
|
|||||||
OPENROUTER_MODEL?: string
|
OPENROUTER_MODEL?: string
|
||||||
GEMINI_API_KEY?: string
|
GEMINI_API_KEY?: string
|
||||||
FLOWGLAD_SECRET_KEY?: string
|
FLOWGLAD_SECRET_KEY?: string
|
||||||
CLOUDFLARE_STREAM_NIKIV_VIDEO_ID?: string
|
CLOUDFLARE_LIVE_INPUT_UID?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ export const Route = createFileRoute("/$username")({
|
|||||||
component: StreamPage,
|
component: StreamPage,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Cloudflare Live Input UID (constant - automatically shows current live stream)
|
|
||||||
const LIVE_INPUT_UID = "bb7858eafc85de6c92963f3817477b5d"
|
|
||||||
const HLS_URL = `https://customer-xctsztqzu046isdc.cloudflarestream.com/${LIVE_INPUT_UID}/manifest/video.m3u8`
|
|
||||||
const READY_PULSE_MS = 1200
|
const READY_PULSE_MS = 1200
|
||||||
|
|
||||||
// Hardcoded user for nikiv (hls_url will be updated from API)
|
// Hardcoded user for nikiv (hls_url will be updated from API)
|
||||||
@@ -59,6 +56,7 @@ function StreamPage() {
|
|||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [playerReady, setPlayerReady] = useState(false)
|
const [playerReady, setPlayerReady] = useState(false)
|
||||||
const [hlsLive, setHlsLive] = useState<boolean | null>(null)
|
const [hlsLive, setHlsLive] = useState<boolean | null>(null)
|
||||||
|
const [hlsUrl, setHlsUrl] = useState<string | null>(null)
|
||||||
const [isConnecting, setIsConnecting] = useState(false)
|
const [isConnecting, setIsConnecting] = useState(false)
|
||||||
const [nowPlaying, setNowPlaying] = useState<SpotifyNowPlayingResponse | null>(
|
const [nowPlaying, setNowPlaying] = useState<SpotifyNowPlayingResponse | null>(
|
||||||
null,
|
null,
|
||||||
@@ -78,9 +76,12 @@ function StreamPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isActive = true
|
let isActive = true
|
||||||
|
|
||||||
// Special handling for nikiv - hardcoded stream with constant Live Input URL
|
// Special handling for nikiv - URL comes from API (secret)
|
||||||
if (username === "nikiv") {
|
if (username === "nikiv") {
|
||||||
setData(makeNikivData(HLS_URL))
|
// Data will be set when we get the HLS URL from the API
|
||||||
|
if (hlsUrl) {
|
||||||
|
setData(makeNikivData(hlsUrl))
|
||||||
|
}
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
return () => {
|
return () => {
|
||||||
isActive = false
|
isActive = false
|
||||||
@@ -168,9 +169,9 @@ function StreamPage() {
|
|||||||
}, [playerReady])
|
}, [playerReady])
|
||||||
|
|
||||||
const stream = data?.stream ?? null
|
const stream = data?.stream ?? null
|
||||||
// For nikiv, always use HLS directly (no WebRTC)
|
// For nikiv, always use HLS directly (no WebRTC) - URL comes from API
|
||||||
const activePlayback = username === "nikiv"
|
const activePlayback = username === "nikiv" && hlsUrl
|
||||||
? { type: "hls" as const, url: HLS_URL }
|
? { type: "hls" as const, url: hlsUrl }
|
||||||
: stream?.playback ?? null
|
: stream?.playback ?? null
|
||||||
|
|
||||||
const isHlsPlaylistLive = (manifest: string) => {
|
const isHlsPlaylistLive = (manifest: string) => {
|
||||||
@@ -184,7 +185,7 @@ function StreamPage() {
|
|||||||
return isValidManifest && !hasEndlist && !isVod && hasSegments
|
return isValidManifest && !hasEndlist && !isVod && hasSegments
|
||||||
}
|
}
|
||||||
|
|
||||||
// For nikiv, use server-side API to check HLS (avoids CORS)
|
// For nikiv, use server-side API to check HLS (avoids CORS, gets URL from secret)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (username !== "nikiv") return
|
if (username !== "nikiv") return
|
||||||
|
|
||||||
@@ -197,6 +198,12 @@ function StreamPage() {
|
|||||||
|
|
||||||
const apiData = await res.json()
|
const apiData = await res.json()
|
||||||
|
|
||||||
|
// Update HLS URL from API (comes from server secret)
|
||||||
|
if (apiData.hlsUrl && apiData.hlsUrl !== hlsUrl) {
|
||||||
|
setHlsUrl(apiData.hlsUrl)
|
||||||
|
setData(makeNikivData(apiData.hlsUrl))
|
||||||
|
}
|
||||||
|
|
||||||
if (apiData.isLive) {
|
if (apiData.isLive) {
|
||||||
// Stream is live - set connecting state if first time
|
// Stream is live - set connecting state if first time
|
||||||
if (!hasConnectedOnce.current) {
|
if (!hasConnectedOnce.current) {
|
||||||
@@ -226,7 +233,7 @@ function StreamPage() {
|
|||||||
isActive = false
|
isActive = false
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
}
|
}
|
||||||
}, [username])
|
}, [username, hlsUrl])
|
||||||
|
|
||||||
// For non-nikiv users, use direct HLS check
|
// For non-nikiv users, use direct HLS check
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -6,12 +6,22 @@ const json = (data: unknown, status = 200) =>
|
|||||||
headers: { "content-type": "application/json" },
|
headers: { "content-type": "application/json" },
|
||||||
})
|
})
|
||||||
|
|
||||||
// Cloudflare Live Input UID (constant - automatically shows current live stream)
|
// Cloudflare customer subdomain
|
||||||
const LIVE_INPUT_UID = "bb7858eafc85de6c92963f3817477b5d"
|
const CLOUDFLARE_CUSTOMER_CODE = "xctsztqzu046isdc"
|
||||||
const HLS_URL = `https://customer-xctsztqzu046isdc.cloudflarestream.com/${LIVE_INPUT_UID}/manifest/video.m3u8`
|
|
||||||
|
|
||||||
function getHlsUrl(): string {
|
function getHlsUrl(): string {
|
||||||
return HLS_URL
|
try {
|
||||||
|
const { getServerContext } = require("@tanstack/react-start/server") as {
|
||||||
|
getServerContext: () => { cloudflare?: { env?: Record<string, string> } } | null
|
||||||
|
}
|
||||||
|
const ctx = getServerContext()
|
||||||
|
const liveInputUid = ctx?.cloudflare?.env?.CLOUDFLARE_LIVE_INPUT_UID
|
||||||
|
if (liveInputUid) {
|
||||||
|
return `https://customer-${CLOUDFLARE_CUSTOMER_CODE}.cloudflarestream.com/${liveInputUid}/manifest/video.m3u8`
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
// Fallback - should not happen in production
|
||||||
|
throw new Error("CLOUDFLARE_LIVE_INPUT_UID not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
function isHlsPlaylistLive(manifest: string): boolean {
|
function isHlsPlaylistLive(manifest: string): boolean {
|
||||||
|
|||||||
@@ -29,8 +29,7 @@
|
|||||||
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
|
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
|
||||||
*/
|
*/
|
||||||
"vars": {
|
"vars": {
|
||||||
"APP_BASE_URL": "https://linsa.io",
|
"APP_BASE_URL": "https://linsa.io"
|
||||||
"CLOUDFLARE_LIVE_INPUT_UID": "bb7858eafc85de6c92963f3817477b5d"
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Note: Use secrets to store sensitive data.
|
* Note: Use secrets to store sensitive data.
|
||||||
|
|||||||
Reference in New Issue
Block a user