mirror of
https://github.com/datascale-ai/opentalking.git
synced 2026-07-03 15:22:34 +08:00
update ecommerce & Huangshan Introduction case
This commit is contained in:
@@ -240,6 +240,9 @@ TRAFFIC_COPY = {
|
||||
"video_names": {
|
||||
"hero-companion-character": "首页主视觉:陪伴类角色",
|
||||
"case-ecommerce-livestream": "案例:电商带货",
|
||||
"case-ecommerce-livestream-front": "案例:电商直播正视",
|
||||
"case-ecommerce-livestream-angle": "案例:电商带货斜视",
|
||||
"case-huangshan-tour-guide": "案例:黄山文旅导览",
|
||||
"case-news-anchor": "案例:新闻主播",
|
||||
"case-companion-character": "案例:陪伴类角色",
|
||||
"case-anime-talk-show": "案例:动漫脱口秀",
|
||||
@@ -323,6 +326,9 @@ TRAFFIC_COPY = {
|
||||
"video_names": {
|
||||
"hero-companion-character": "Hero: Companion Character",
|
||||
"case-ecommerce-livestream": "Case: E-commerce Livestream",
|
||||
"case-ecommerce-livestream-front": "Case: E-commerce Front View",
|
||||
"case-ecommerce-livestream-angle": "Case: E-commerce Angled View",
|
||||
"case-huangshan-tour-guide": "Case: Huangshan Tourism Guide",
|
||||
"case-news-anchor": "Case: News Anchor",
|
||||
"case-companion-character": "Case: Companion Character",
|
||||
"case-anime-talk-show": "Case: Anime Talk Show",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
BIN
apps/homepage/public/images/cases/huangshan-guide-preview.png
Normal file
BIN
apps/homepage/public/images/cases/huangshan-guide-preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 713 KiB |
@@ -16,7 +16,7 @@ export type CaseStudy = {
|
||||
slug: string;
|
||||
title: string;
|
||||
eyebrow: string;
|
||||
category: "livestream" | "media" | "character" | "companion" | "experiment";
|
||||
category: "livestream" | "media" | "tourism" | "character" | "companion" | "experiment";
|
||||
categoryLabel: string;
|
||||
description: string;
|
||||
detailIntro: string;
|
||||
@@ -27,6 +27,13 @@ export type CaseStudy = {
|
||||
accent: "cyan" | "mint" | "amber" | "violet" | "rose" | "slate";
|
||||
comingSoon?: boolean;
|
||||
videoUrl?: string;
|
||||
videoVariants?: Array<{
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
poster?: string;
|
||||
videoId?: string;
|
||||
}>;
|
||||
sections: Array<{
|
||||
title: string;
|
||||
body: string;
|
||||
@@ -83,6 +90,7 @@ export const caseCategories = [
|
||||
{ key: "all", label: "全部场景" },
|
||||
{ key: "livestream", label: "直播带货" },
|
||||
{ key: "media", label: "媒体播报" },
|
||||
{ key: "tourism", label: "文旅导览" },
|
||||
{ key: "character", label: "角色内容" },
|
||||
{ key: "companion", label: "陪伴互动" },
|
||||
{ key: "experiment", label: "创意实验" },
|
||||
@@ -130,11 +138,27 @@ export const caseStudies: CaseStudy[] = [
|
||||
"面向商品讲解、评论问答和直播间陪跑,把语音回复、字幕和实时视频渲染整合到同一链路。",
|
||||
detailIntro:
|
||||
"用 OpenTalking 搭建一个可互动的数字人直播间,让商品介绍、用户问题和优惠转化都能通过实时语音和画面完成。",
|
||||
route: "Local GPU 或 OmniRT 高质量路线",
|
||||
route: "双机位直播带货演示",
|
||||
features: ["实时问答", "角色音色", "字幕同步"],
|
||||
image: "/images/cases/live-sales.jpeg",
|
||||
image: "/images/cases/ecommerce-live-front-preview.png",
|
||||
accent: "amber",
|
||||
videoUrl: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/d9d848c95001834806724661995/SaicQA0Ah7QA.mp4",
|
||||
videoUrl: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/742bcb745001834809665869890/vkxsFysr5REA.mp4",
|
||||
videoVariants: [
|
||||
{
|
||||
title: "正视直播间",
|
||||
description: "正面机位展示商品讲解、优惠信息和直播间视觉元素,适合官网主案例展示。",
|
||||
url: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/742bcb745001834809665869890/vkxsFysr5REA.mp4",
|
||||
poster: "/images/cases/ecommerce-live-front-preview.png",
|
||||
videoId: "case-ecommerce-livestream-front",
|
||||
},
|
||||
{
|
||||
title: "斜视带货机位",
|
||||
description: "加入真实拍摄机位感,突出桌面商品、导购动作和直播场景的空间层次。",
|
||||
url: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/cca683435001834809670031995/aswhi0HNmYkA.mp4",
|
||||
poster: "/images/cases/ecommerce-live-angle-preview.png",
|
||||
videoId: "case-ecommerce-livestream-angle",
|
||||
},
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
title: "场景挑战",
|
||||
@@ -151,6 +175,37 @@ export const caseStudies: CaseStudy[] = [
|
||||
],
|
||||
outcomes: ["商品讲解自动化", "评论问答实时响应", "字幕与视频同步展示"],
|
||||
},
|
||||
{
|
||||
slug: "huangshan-tour-guide",
|
||||
title: "黄山文旅导览",
|
||||
eyebrow: "沉浸讲解",
|
||||
category: "tourism",
|
||||
categoryLabel: "文旅导览",
|
||||
description:
|
||||
"面向景区、城市展馆和文旅宣传,用数字人讲解自然景观、路线亮点和地域文化。",
|
||||
detailIntro:
|
||||
"以黄山介绍为例,把景区画面、导览口播和数字讲解员结合起来,适合游客中心、城市展厅和线上文旅内容展示。",
|
||||
route: "QuickTalk / FlashTalk",
|
||||
features: ["景区讲解", "沉浸画面", "多语言扩展"],
|
||||
image: "/images/cases/huangshan-guide-preview.png",
|
||||
accent: "mint",
|
||||
videoUrl: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/742bcf735001834809665869970/T9jkqMRNCacA.mp4",
|
||||
sections: [
|
||||
{
|
||||
title: "场景挑战",
|
||||
body: "文旅内容既要讲清景点特色,也要保持画面感染力和讲解节奏,传统拍摄更新成本较高。",
|
||||
},
|
||||
{
|
||||
title: "适合扩展",
|
||||
body: "可以接入景区知识库、路线推荐、多语言导览和游客问答,把单条宣传片扩展成可互动的数字导览员。",
|
||||
},
|
||||
{
|
||||
title: "推荐模型",
|
||||
body: "推荐 QuickTalk / FlashTalk:先快速验证导览脚本和画面融合,再按展厅大屏或宣传片质量要求升级。",
|
||||
},
|
||||
],
|
||||
outcomes: ["景区讲解视频化", "导览内容可复用", "支持后续多语言与问答扩展"],
|
||||
},
|
||||
{
|
||||
slug: "news-anchor",
|
||||
title: "新闻主播",
|
||||
|
||||
@@ -150,6 +150,7 @@ const enCaseCategories = [
|
||||
{ key: "all", label: "All" },
|
||||
{ key: "livestream", label: "Live commerce" },
|
||||
{ key: "media", label: "Media" },
|
||||
{ key: "tourism", label: "Tourism" },
|
||||
{ key: "character", label: "Character content" },
|
||||
{ key: "companion", label: "Companion" },
|
||||
{ key: "experiment", label: "Creative demos" },
|
||||
@@ -197,11 +198,27 @@ const enCaseStudies: CaseStudy[] = [
|
||||
"Combine product narration, audience Q&A, captions, speech, and real-time avatar video in one live commerce workflow.",
|
||||
detailIntro:
|
||||
"Build an interactive AI host that can follow product scripts, answer audience questions, and present offers with synchronized voice and video.",
|
||||
route: "Local GPU or OmniRT quality route",
|
||||
route: "Two-view live commerce demo",
|
||||
features: ["Real-time Q&A", "Voice persona", "Caption sync"],
|
||||
image: "/images/cases/live-sales.jpeg",
|
||||
image: "/images/cases/ecommerce-live-front-preview.png",
|
||||
accent: "amber",
|
||||
videoUrl: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/d9d848c95001834806724661995/SaicQA0Ah7QA.mp4",
|
||||
videoUrl: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/742bcb745001834809665869890/vkxsFysr5REA.mp4",
|
||||
videoVariants: [
|
||||
{
|
||||
title: "Front-facing livestream",
|
||||
description: "A direct host view for product explanation, offer highlights, and live commerce UI elements.",
|
||||
url: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/742bcb745001834809665869890/vkxsFysr5REA.mp4",
|
||||
poster: "/images/cases/ecommerce-live-front-preview.png",
|
||||
videoId: "case-ecommerce-livestream-front",
|
||||
},
|
||||
{
|
||||
title: "Angled selling setup",
|
||||
description: "A more realistic camera angle with visible products, presenter movement, and livestream staging.",
|
||||
url: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/cca683435001834809670031995/aswhi0HNmYkA.mp4",
|
||||
poster: "/images/cases/ecommerce-live-angle-preview.png",
|
||||
videoId: "case-ecommerce-livestream-angle",
|
||||
},
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
title: "Scenario Challenge",
|
||||
@@ -218,6 +235,37 @@ const enCaseStudies: CaseStudy[] = [
|
||||
],
|
||||
outcomes: ["Automated product narration", "Real-time audience response", "Synchronized captions and video"],
|
||||
},
|
||||
{
|
||||
slug: "huangshan-tour-guide",
|
||||
title: "Huangshan Tourism Guide",
|
||||
eyebrow: "Immersive narration",
|
||||
category: "tourism",
|
||||
categoryLabel: "Tourism",
|
||||
description:
|
||||
"Use an avatar guide to introduce scenic areas, travel routes, cultural highlights, and destination stories.",
|
||||
detailIntro:
|
||||
"This Huangshan example combines scenic footage, guide narration, and a digital presenter for visitor centers, city exhibitions, and online tourism campaigns.",
|
||||
route: "QuickTalk / FlashTalk",
|
||||
features: ["Scenic narration", "Immersive visuals", "Multilingual-ready"],
|
||||
image: "/images/cases/huangshan-guide-preview.png",
|
||||
accent: "mint",
|
||||
videoUrl: "https://1441945933.vod-qcloud.com/0b66444dvodcq1441945933/742bcf735001834809665869970/T9jkqMRNCacA.mp4",
|
||||
sections: [
|
||||
{
|
||||
title: "Scenario Challenge",
|
||||
body: "Tourism videos need clear destination storytelling, strong visuals, and a consistent narration rhythm, while updates can be costly with traditional shoots.",
|
||||
},
|
||||
{
|
||||
title: "Extension Path",
|
||||
body: "Connect destination knowledge, route recommendations, multilingual narration, and visitor Q&A to turn a video into an interactive digital guide.",
|
||||
},
|
||||
{
|
||||
title: "Recommended Model",
|
||||
body: "Recommended: QuickTalk / FlashTalk. Start by validating narration and scene composition, then upgrade quality for exhibition screens or destination campaigns.",
|
||||
},
|
||||
],
|
||||
outcomes: ["Turn scenic content into guided video", "Reuse destination scripts", "Extend to multilingual Q&A later"],
|
||||
},
|
||||
{
|
||||
slug: "news-anchor",
|
||||
title: "News Anchor",
|
||||
@@ -479,7 +527,7 @@ export const siteContent: Record<Language, SiteContent> = {
|
||||
capabilityDescription: "OpenTalking 把会话、语音、字幕、播放和模型服务串成完整的数字人产品链路。",
|
||||
showcaseEyebrow: "Showcase",
|
||||
showcaseTitle: "真实产品场景,为数字人服务而生",
|
||||
showcaseDescription: "用同一套编排层覆盖直播、播报、陪伴、角色内容和端到端演示。",
|
||||
showcaseDescription: "用同一套编排层覆盖直播、文旅导览、播报、陪伴、角色内容和端到端演示。",
|
||||
allCasesCta: "全部案例",
|
||||
deploymentEyebrow: "Deployment",
|
||||
deploymentTitle: "按你的需求匹配不同部署方式",
|
||||
@@ -603,7 +651,7 @@ export const siteContent: Record<Language, SiteContent> = {
|
||||
capabilityDescription: "OpenTalking connects dialogue, voice, captions, playback, and model services into a complete AI avatar workflow.",
|
||||
showcaseEyebrow: "Showcase",
|
||||
showcaseTitle: "Built for real avatar use cases",
|
||||
showcaseDescription: "Use the same orchestration layer for livestreaming, broadcast, companion experiences, character content, and end-to-end demos.",
|
||||
showcaseDescription: "Use the same orchestration layer for livestreaming, tourism guides, broadcast, companion experiences, character content, and end-to-end demos.",
|
||||
allCasesCta: "All cases",
|
||||
deploymentEyebrow: "Deployment",
|
||||
deploymentTitle: "Pick the right path for your stage",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ArrowLeft, CheckCircle2, ExternalLink, PlayCircle } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { trackAnalyticsEvent } from "../analytics";
|
||||
import { CaseCard } from "../components/CaseCard";
|
||||
import type { CaseStudy } from "../content";
|
||||
@@ -19,6 +20,32 @@ export function CaseDetailPage({
|
||||
onBack,
|
||||
onOpenCase,
|
||||
}: CaseDetailPageProps) {
|
||||
const videoItems = useMemo(() => {
|
||||
if (item.videoVariants?.length) {
|
||||
return item.videoVariants;
|
||||
}
|
||||
|
||||
if (!item.videoUrl) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
title: copy.videoTitle,
|
||||
description: item.route,
|
||||
url: item.videoUrl,
|
||||
poster: item.image,
|
||||
videoId: `case-${item.slug}`,
|
||||
},
|
||||
];
|
||||
}, [copy.videoTitle, item]);
|
||||
const [activeVideoIndex, setActiveVideoIndex] = useState(0);
|
||||
const activeVideo = videoItems[Math.min(activeVideoIndex, Math.max(videoItems.length - 1, 0))];
|
||||
|
||||
useEffect(() => {
|
||||
setActiveVideoIndex(0);
|
||||
}, [item.slug]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="case-detail-hero">
|
||||
@@ -51,17 +78,18 @@ export function CaseDetailPage({
|
||||
<section className="section-container">
|
||||
<div className="grid gap-8 lg:grid-cols-[1fr_340px]">
|
||||
<article className="grid gap-6">
|
||||
{item.videoUrl ? (
|
||||
{activeVideo ? (
|
||||
<div className="video-panel">
|
||||
<div className="flex items-center gap-2 border-b border-white/14 px-5 py-4 text-white">
|
||||
<PlayCircle className="h-5 w-5 text-indigo-200" />
|
||||
<span className="font-semibold">{copy.videoTitle}</span>
|
||||
</div>
|
||||
<video
|
||||
key={activeVideo.url}
|
||||
className="aspect-video w-full bg-black"
|
||||
src={item.videoUrl}
|
||||
src={activeVideo.url}
|
||||
controls
|
||||
poster={item.image}
|
||||
poster={activeVideo.poster ?? item.image}
|
||||
onPlay={() =>
|
||||
trackAnalyticsEvent({
|
||||
eventName: "video_play",
|
||||
@@ -69,10 +97,42 @@ export function CaseDetailPage({
|
||||
language: window.location.pathname === "/en" || window.location.pathname.startsWith("/en/") ? "en" : "zh",
|
||||
page: "caseDetail",
|
||||
caseSlug: item.slug,
|
||||
videoId: `case-${item.slug}`,
|
||||
videoId: activeVideo.videoId ?? `case-${item.slug}`,
|
||||
})
|
||||
}
|
||||
/>
|
||||
{videoItems.length > 1 ? (
|
||||
<div className="grid gap-3 border-t border-white/14 bg-indigo-950/95 p-4 md:grid-cols-2">
|
||||
{videoItems.map((video, index) => {
|
||||
const isActive = index === activeVideoIndex;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={video.url}
|
||||
type="button"
|
||||
className={`group flex cursor-pointer gap-3 rounded-lg border p-2 text-left transition duration-300 ${
|
||||
isActive
|
||||
? "border-cyanline bg-white text-ink"
|
||||
: "border-white/14 bg-white/10 text-white hover:border-white/30 hover:bg-white/20"
|
||||
}`}
|
||||
onClick={() => setActiveVideoIndex(index)}
|
||||
>
|
||||
<img
|
||||
src={video.poster ?? item.image}
|
||||
alt={`${video.title} preview`}
|
||||
className="h-16 w-24 shrink-0 rounded-md object-cover"
|
||||
/>
|
||||
<span className="min-w-0">
|
||||
<span className="block text-sm font-semibold">{video.title}</span>
|
||||
<span className={`mt-1 block max-h-10 overflow-hidden text-xs leading-5 ${isActive ? "text-slate-600" : "text-white/70"}`}>
|
||||
{video.description}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user