Lecteur vidéo avec Claude Code
Découvrez lecteur vidéo avec Claude Code. Conseils pratiques et exemples de code inclus.
カスタム動画プレーヤーをClaude Codeで作る
デフォルトのブラウザ動画プレーヤーではデザインの統一が難しく、機能も限定されます。Claude Codeを使えば、ブランドに合ったデザインで、再生速度変更・字幕・ピクチャーインピクチャーなどの機能を備えたカスタムプレーヤーを構築できます。
プレーヤーの要件
> HTML5 Videoベースのカスタム動画プレーヤーを作って。
> 再生/一時停止、シークバー、音量、再生速度変更、
> フルスクリーン、ピクチャーインピクチャー、字幕表示に対応して。
メインプレーヤーコンポーネント
// src/components/VideoPlayer.tsx
'use client';
import { useRef, useState, useEffect } from 'react';
interface VideoPlayerProps {
src: string;
poster?: string;
subtitles?: { src: string; label: string; lang: string }[];
}
export function VideoPlayer({ src, poster, subtitles }: VideoPlayerProps) {
const videoRef = useRef<HTMLVideoElement>(null);
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
const [volume, setVolume] = useState(1);
const [playbackRate, setPlaybackRate] = useState(1);
const [showControls, setShowControls] = useState(true);
const video = videoRef.current;
useEffect(() => {
if (!video) return;
const handleTimeUpdate = () => setCurrentTime(video.currentTime);
const handleLoadedMetadata = () => setDuration(video.duration);
video.addEventListener('timeupdate', handleTimeUpdate);
video.addEventListener('loadedmetadata', handleLoadedMetadata);
return () => {
video.removeEventListener('timeupdate', handleTimeUpdate);
video.removeEventListener('loadedmetadata', handleLoadedMetadata);
};
}, [video]);
const togglePlay = () => {
if (!video) return;
if (video.paused) {
video.play();
setIsPlaying(true);
} else {
video.pause();
setIsPlaying(false);
}
};
const handleSeek = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!video) return;
const time = Number(e.target.value);
video.currentTime = time;
setCurrentTime(time);
};
const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!video) return;
const vol = Number(e.target.value);
video.volume = vol;
setVolume(vol);
};
const changePlaybackRate = (rate: number) => {
if (!video) return;
video.playbackRate = rate;
setPlaybackRate(rate);
};
const toggleFullscreen = () => {
const container = videoRef.current?.parentElement;
if (!container) return;
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
container.requestFullscreen();
}
};
const togglePiP = async () => {
if (!video) return;
if (document.pictureInPictureElement) {
await document.exitPictureInPicture();
} else {
await video.requestPictureInPicture();
}
};
const formatTime = (seconds: number) => {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, '0')}`;
};
return (
<div
className="relative group bg-black rounded-xl overflow-hidden"
onMouseEnter={() => setShowControls(true)}
onMouseLeave={() => isPlaying && setShowControls(false)}
>
<video
ref={videoRef}
src={src}
poster={poster}
onClick={togglePlay}
className="w-full cursor-pointer"
>
{subtitles?.map((sub) => (
<track key={sub.lang} kind="subtitles" src={sub.src} label={sub.label} srcLang={sub.lang} />
))}
</video>
{/* コントロールバー */}
<div className={`absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-4 transition-opacity ${showControls ? 'opacity-100' : 'opacity-0'}`}>
{/* シークバー */}
<input
type="range"
min={0}
max={duration}
value={currentTime}
onChange={handleSeek}
className="w-full h-1 mb-3 accent-blue-500"
/>
<div className="flex items-center justify-between text-white text-sm">
<div className="flex items-center gap-3">
<button onClick={togglePlay} className="text-xl">
{isPlaying ? '⏸' : '▶'}
</button>
<span>{formatTime(currentTime)} / {formatTime(duration)}</span>
<input
type="range"
min={0}
max={1}
step={0.1}
value={volume}
onChange={handleVolumeChange}
className="w-20 h-1 accent-white"
/>
</div>
<div className="flex items-center gap-3">
<select
value={playbackRate}
onChange={(e) => changePlaybackRate(Number(e.target.value))}
className="bg-transparent text-white text-sm"
>
{[0.5, 0.75, 1, 1.25, 1.5, 2].map((rate) => (
<option key={rate} value={rate} className="text-black">
{rate}x
</option>
))}
</select>
<button onClick={togglePiP} title="ピクチャーインピクチャー">🖼</button>
<button onClick={toggleFullscreen} title="フルスクリーン">⛶</button>
</div>
</div>
</div>
</div>
);
}
キーボードショートカット
// src/hooks/useVideoShortcuts.ts
import { useEffect } from 'react';
export function useVideoShortcuts(videoRef: React.RefObject<HTMLVideoElement>) {
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
const video = videoRef.current;
if (!video) return;
switch (e.key) {
case ' ':
e.preventDefault();
video.paused ? video.play() : video.pause();
break;
case 'ArrowRight':
video.currentTime = Math.min(video.currentTime + 10, video.duration);
break;
case 'ArrowLeft':
video.currentTime = Math.max(video.currentTime - 10, 0);
break;
case 'f':
document.fullscreenElement
? document.exitFullscreen()
: video.parentElement?.requestFullscreen();
break;
case 'm':
video.muted = !video.muted;
break;
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [videoRef]);
}
使い方の例
<VideoPlayer
src="/videos/demo.mp4"
poster="/images/poster.jpg"
subtitles={[
{ src: '/subtitles/ja.vtt', label: '日本語', lang: 'ja' },
{ src: '/subtitles/en.vtt', label: 'English', lang: 'en' },
]}
/>
関連記事
メディア関連ではオーディオプレーヤーの実装、アクセシビリティ対応はアクセシビリティ実装ガイドもご覧ください。
Web動画のフォーマットやエンコーディングについてはMDN Web Docs(developer.mozilla.org)が詳しいです。
PDF gratuit : aide-mémoire Claude Code en 5 minutes
Laissez simplement votre e-mail et nous vous enverrons immédiatement l'aide-mémoire A4 en PDF.
Nous traitons vos données avec soin et n'envoyons jamais de spam.
À propos de l'auteur
Masa
Ingénieur passionné par Claude Code. Il gère claudecode-lab.com, un média tech en 10 langues avec plus de 2 000 pages.
Articles similaires
7 vérifications avant de publier chaque jour un article multilingue sur Claude Code
Une checklist pratique pour publier des articles multilingues sur Claude Code chaque jour sans oublier une langue, casser les CTA ou laisser l’ancien contenu en production.
Codex Automations : confier l'analyse, les articles et le deploiement a l'IA
Guide pratique pour utiliser Codex Automations dans une operation de contenu orientee monetisation.
Claude Code × GCP Cloud Functions Guide Complet | Développement Serverless Ultra-Rapide
Optimisez GCP Cloud Functions avec Claude Code. Implémentez des triggers HTTP/Pub/Sub/Firestore, des tests locaux et l'automatisation des déploiements avec des exemples de code réels de l'expérience de Masa.