V

video-producer

by @daffy0208v1.0.0
0.0(0)

帮助您构建视频播放器、处理视频流和管理视频内容,提供全面的视频解决方案。

Video ProductionVideo StreamingMedia PlaybackMultimedia DevelopmentGitHub
安装方式
npx skills add daffy0208/ai-dev-standards --skill video-producer
compare_arrows

Before / After 效果对比

1
使用前

视频播放器开发复杂,流媒体处理困难,用户体验差。

使用后

构建高性能视频播放器,优化流媒体,提升用户观看体验。

description SKILL.md

video-producer

Video Producer Skill I help you build video players, handle video streaming, and create engaging video experiences. What I Do Video Playback: Custom video players with controls Adaptive bitrate streaming (HLS, DASH) Picture-in-picture mode Fullscreen support Video Features: Subtitles and captions Quality selection Playback speed control Thumbnail previews Streaming: Live video streaming Video on demand (VOD) Progressive download Adaptive streaming Custom Video Player // components/VideoPlayer.tsx 'use client' import { useRef, useState, useEffect } from 'react' interface VideoPlayerProps { src: string poster?: string title?: string } export function VideoPlayer({ src, poster, title }: VideoPlayerProps) { const videoRef = useRef(null) const [playing, setPlaying] = useState(false) const [currentTime, setCurrentTime] = useState(0) const [duration, setDuration] = useState(0) const [volume, setVolume] = useState(1) const [fullscreen, setFullscreen] = useState(false) const [showControls, setShowControls] = useState(true) useEffect(() => { const video = videoRef.current if (!video) return const updateTime = () => setCurrentTime(video.currentTime) const updateDuration = () => setDuration(video.duration) const handleEnded = () => setPlaying(false) video.addEventListener('timeupdate', updateTime) video.addEventListener('loadedmetadata', updateDuration) video.addEventListener('ended', handleEnded) return () => { video.removeEventListener('timeupdate', updateTime) video.removeEventListener('loadedmetadata', updateDuration) video.removeEventListener('ended', handleEnded) } }, []) const togglePlay = () => { if (!videoRef.current) return if (playing) { videoRef.current.pause() } else { videoRef.current.play() } setPlaying(!playing) } const handleSeek = (e: React.ChangeEvent) => { const time = parseFloat(e.target.value) setCurrentTime(time) if (videoRef.current) { videoRef.current.currentTime = time } } const handleVolumeChange = (e: React.ChangeEvent) => { const vol = parseFloat(e.target.value) setVolume(vol) if (videoRef.current) { videoRef.current.volume = vol } } const toggleFullscreen = () => { if (!videoRef.current) return if (!fullscreen) { videoRef.current.requestFullscreen() } else { document.exitFullscreen() } setFullscreen(!fullscreen) } const formatTime = (seconds: number) => { const mins = Math.floor(seconds / 60) const secs = Math.floor(seconds % 60) return ${mins}:${secs.toString().padStart(2, '0')} } return ( <div className="relative bg-black rounded-lg overflow-hidden" onMouseEnter={() => setShowControls(true)} onMouseLeave={() => setShowControls(playing ? false : true)} > {title && ( {title} )} {showControls && ( {/* Progress Bar /} <input type="range" min="0" max={duration || 0} value={currentTime} onChange={handleSeek} className="w-full mb-2" /> {/ Play/Pause /} {playing ? '⏸️' : '▶️'} {/ Time /} {formatTime(currentTime)} / {formatTime(duration)} {/ Volume /} 🔊 {/ Fullscreen /} {fullscreen ? '⬛' : '⬜'} )} ) } HLS Streaming (Adaptive Bitrate) npm install hls.js // components/HLSPlayer.tsx 'use client' import { useEffect, useRef } from 'react' import Hls from 'hls.js' export function HLSPlayer({ src }: { src: string }) { const videoRef = useRef(null) useEffect(() => { const video = videoRef.current if (!video) return if (Hls.isSupported()) { const hls = new Hls({ enableWorker: true, lowLatencyMode: true }) hls.loadSource(src) hls.attachMedia(video) hls.on(Hls.Events.MANIFEST_PARSED, () => { console.log('HLS manifest loaded, quality levels:', hls.levels) }) hls.on(Hls.Events.ERROR, (event, data) => { console.error('HLS error:', data) if (data.fatal) { switch (data.type) { case Hls.ErrorTypes.NETWORK_ERROR: hls.startLoad() break case Hls.ErrorTypes.MEDIA_ERROR: hls.recoverMediaError() break default: hls.destroy() break } } }) return () => { hls.destroy() } } else if (video.canPlayType('application/vnd.apple.mpegurl')) { // Native HLS support (Safari) video.src = src } }, [src]) return } Picture-in-Picture // components/PIPVideoPlayer.tsx 'use client' import { useRef, useState } from 'react' export function PIPVideoPlayer({ src }: { src: string }) { const videoRef = useRef(null) const [pipActive, setPipActive] = useState(false) const togglePIP = async () => { if (!videoRef.current) return try { if (!pipActive) { await videoRef.current.requestPictureInPicture() setPipActive(true) } else { await document.exitPictureInPicture() setPipActive(false) } } catch (error) { console.error('PIP error:', error) } } return ( {pipActive ? 'Exit PIP' : 'Enter PIP'} ) } Subtitles/Captions // components/VideoWithSubtitles.tsx 'use client' export function VideoWithSubtitles() { return ( ) } VTT Subtitle File: WEBVTT 00:00:00.000 --> 00:00:02.000 Hello, welcome to our video. 00:00:02.500 --> 00:00:05.000 Today we'll learn about web development. 00:00:05.500 --> 00:00:08.000 Let's get started! Quality Selection // components/QualitySelector.tsx 'use client' import { useState } from 'react' const qualities = [ { label: '1080p', src: '/video-1080p.mp4' }, { label: '720p', src: '/video-720p.mp4' }, { label: '480p', src: '/video-480p.mp4' }, { label: '360p', src: '/video-360p.mp4' } ] export function QualitySelector() { const [currentQuality, setCurrentQuality] = useState(qualities[1]) return ( Quality: <select value={currentQuality.label} onChange={(e) => { const quality = qualities.find(q => q.label === e.target.value) if (quality) setCurrentQuality(quality) }} className="px-4 py-2 border rounded" > {qualities.map((q) => ( {q.label} ))} ) } Playback Speed Control // components/PlaybackSpeed.tsx 'use client' import { useRef, useState } from 'react' const speeds = [0.5, 0.75, 1, 1.25, 1.5, 2] export function PlaybackSpeed({ src }: { src: string }) { const videoRef = useRef(null) const [speed, setSpeed] = useState(1) const handleSpeedChange = (newSpeed: number) => { setSpeed(newSpeed) if (videoRef.current) { videoRef.current.playbackRate = newSpeed } } return ( Speed: {speeds.map((s) => ( <button key={s} onClick={() => handleSpeedChange(s)} className={px-3 py-1 rounded ${ speed === s ? 'bg-blue-600 text-white' : 'bg-gray-200' }} > {s}x ))} ) } Video Thumbnail on Hover // components/VideoThumbnailPreview.tsx 'use client' import { useState } from 'react' export function VideoThumbnailPreview({ videoSrc }: { videoSrc: string }) { const [thumbnailTime, setThumbnailTime] = useState(0) const handleProgressHover = (e: React.MouseEvent) => { const rect = e.currentTarget.getBoundingClientRect() const percent = (e.clientX - rect.left) / rect.width // Assuming 60 second video setThumbnailTime(percent * 60) } return ( {/ Thumbnail preview */} <div className="absolute bottom-4 -translate-x-1/2 pointer-events-none" style={{ left: ${(thumbnailTime / 60) * 100}% }} > {Math.floor(thumbnailTime)}s ) } Video Upload with Progress // components/VideoUpload.tsx 'use client' import { useState } from 'react' export function VideoUpload() { const [uploading, setUploading] = useState(false) const [progress, setProgress] = useState(0) const [videoURL, setVideoURL] = useState<string | null>(null) const handleUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0] if (!file) return setUploading(true) setProgress(0) const formData = new FormData() formData.append('video', file) const xhr = new XMLHttpRequest() xhr.upload.addEventListener('progress', (e) => { if (e.lengthComputable) { const percentComplete = (e.loaded / e.total) * 100 setProgress(percentComplete) } }) xhr.addEventListener('load', () => { if (xhr.status === 200) { const response = JSON.parse(xhr.responseText) setVideoURL(response.url) } setUploading(false) }) xhr.open('POST', '/api/upload/video') xhr.send(formData) } return ( {uploading && ( <div className="h-full bg-blue-600 transition-all" style={{ width: ${progress}% }} /> Uploading: {Math.round(progress)}% )} {videoURL && ( )} ) } When to Use Me Perfect for: Building video platforms Adding video content Implementing video streaming Creating video courses Building video players I'll help you: Build custom video players Implement HLS streaming Add subtitles/captions Support multiple qualities Handle video uploads What I'll Create 🎥 Custom Video Players 📺 HLS/Adaptive Streaming 📝 Subtitles & Captions ⚙️ Quality Selection ⏩ Playback Speed Control 🖼️ Picture-in-Picture Let's create amazing video experiences!Weekly Installs207Repositorydaffy0208/ai-de…tandardsGitHub Stars21First SeenJan 20, 2026Security AuditsGen Agent Trust HubPassSocketPassSnykPassInstalled onopencode190gemini-cli183codex178cursor171github-copilot167amp149

forum用户评价 (0)

发表评价

效果
易用性
文档
兼容性

暂无评价,来写第一条吧

统计数据

安装量0
评分0.0 / 5.0
版本1.0.0
更新日期2026年3月18日
对比案例1 组

用户评分

0.0(0)
5
0%
4
0%
3
0%
2
0%
1
0%

为此 Skill 评分

0.0

兼容平台

🔧Claude Code

时间线

创建2026年3月18日
最后更新2026年3月18日