diff --git a/package-lock.json b/package-lock.json index 88f7f2e..b1b327b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,9 @@ "@tanstack/react-virtual": "^3.13.12", "client-only": "^0.0.1", "clsx": "^2.1.1", + "hls.js": "^1.6.13", "idb": "^8.0.3", + "media-chrome": "^4.15.0", "next": "15.3.3", "next-intl": "^4.1.0", "react": "^19.0.0", @@ -22,6 +24,7 @@ "remark-gfm": "^4.0.1", "sass": "^1.89.2", "server-only": "^0.0.1", + "shaka-player": "^4.16.7", "socket.io-client": "^4.8.1", "zod": "^3.25.64", "zustand": "^5.0.5" @@ -4629,14 +4632,13 @@ ], "license": "CC-BY-4.0" }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/ce-la-react": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ce-la-react/-/ce-la-react-0.3.1.tgz", + "integrity": "sha512-g0YwpZDPIwTwFumGTzNHcgJA6VhFfFCJkSNdUdC04br2UfU+56JDrJrJva3FZ7MToB4NDHAFBiPE/PZdNl1mQA==", + "license": "BSD-3-Clause", + "peerDependencies": { + "react": ">=17.0.0" } }, "node_modules/chalk": { @@ -6449,6 +6451,12 @@ "type": "opencollective", "url": "https://opencollective.com/unified" } + } + "node_modules/hls.js": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.13.tgz", + "integrity": "sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA==", + "license": "Apache-2.0" }, "node_modules/idb": { "version": "8.0.3", @@ -7282,6 +7290,20 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "node_modules/media-chrome": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.15.0.tgz", + "integrity": "sha512-OgC6m3Ss4cCUEVhvmRdUbnExqVKf8CDRDmbVTjIuRGAXdmz/vc34fL3onSsOm2uDZbhDB4Lb4KArGA48wG8Puw==", + "license": "MIT", + "dependencies": { + "ce-la-react": "^0.3.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -9227,6 +9249,15 @@ "node": ">= 0.4" } }, + "node_modules/shaka-player": { + "version": "4.16.7", + "resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-4.16.7.tgz", + "integrity": "sha512-JWIVIxXRDkmogT+3t7UtYDbqY0dHyrfpqYPkKsyTXqBimwEgKFJIayhxwYF7Cn/qTkhp2nocHIdzaVZkaZLK4A==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/sharp": { "version": "0.34.2", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", diff --git a/package.json b/package.json index 8f567e2..767018e 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "@tanstack/react-virtual": "^3.13.12", "client-only": "^0.0.1", "clsx": "^2.1.1", + "hls.js": "^1.6.13", "idb": "^8.0.3", + "media-chrome": "^4.15.0", "next": "15.3.3", "next-intl": "^4.1.0", "react": "^19.0.0", @@ -27,6 +29,7 @@ "remark-gfm": "^4.0.1", "sass": "^1.89.2", "server-only": "^0.0.1", + "shaka-player": "^4.16.7", "socket.io-client": "^4.8.1", "zod": "^3.25.64", "zustand": "^5.0.5" diff --git a/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx b/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx index c00c357..1edebfb 100644 --- a/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx +++ b/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx @@ -1,12 +1,15 @@ "use client"; import { useEffect, useState } from "react"; +import dynamic from "next/dynamic"; import { useRouter } from "next/navigation"; import { Icon, IconName, MarkdownText, Typography } from "@/components/ui"; import styles from "./VideoGuideView.module.scss"; +const VideoPlayer = dynamic(() => import("../VideoPlayer"), { ssr: false }); + interface VideoGuideViewProps { id: string; name: string; @@ -48,24 +51,12 @@ export default function VideoGuideView({ loadMarkdown(); }, [contentUrl]); - // Extract video ID from various YouTube URL formats - const getYouTubeVideoId = (url: string): string | null => { - const patterns = [ - /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, - /^([a-zA-Z0-9_-]{11})$/, // Direct video ID - ]; + // TODO: Remove hardcoded URLs when backend is ready + // Temporary hardcoded DASH/HLS URLs - using for ALL videos until backend updated + const dashUrl = "https://video.witlab.us/videos/TALK_FEELINGS/cmaf/source.mpd"; + const hlsUrl = "https://video.witlab.us/videos/TALK_FEELINGS/cmaf/source.m3u8"; - for (const pattern of patterns) { - const match = url.match(pattern); - if (match) return match[1]; - } - return null; - }; - - const videoId = getYouTubeVideoId(videoLink); - const embedUrl = videoId - ? `https://www.youtube.com/embed/${videoId}?rel=0&modestbranding=1` - : videoLink; + const _originalVideoLink = videoLink; // Keep for reference when backend is ready return (
@@ -88,15 +79,7 @@ export default function VideoGuideView({
{/* Video Player */}
-
-