๐Ÿ‡ฎ๐Ÿ‡ณ
๐Ÿ‡ฎ๐Ÿ‡ณ
Republic Day Special Offer!Get 20% OFF on all courses
Enroll Now
P
Prakalpana
๐Ÿ“šLearn
โ€ขCode Your Future
Interview Prepโฑ๏ธ 23 min read๐Ÿ“… Dec 21

UI Interview: Design YouTube Video Player (Complete Mock)

RK
Rohit Kumarโ€ขSenior Engineer at YouTube
๐Ÿ“‘ Contents (11 sections)

๐Ÿ“ŒThe Interview Setting

Company: YouTube/Google Round: Frontend System Design Duration: 45 minutes

๐Ÿ“Œ๐ŸŽค Interviewer: "Design a video player like YouTube."

Candidate's Clarifications:

  • 1Adaptive streaming (quality switching)?
  • 2Features: subtitles, playback speed, fullscreen?
  • 3Live streaming support?
  • 4Picture-in-picture, theater mode?
  • Interviewer: "Yes to adaptive streaming. Include subtitles, speed. Skip live for now."

    ๐Ÿ“Œ๐Ÿ“ Component Architecture

    VideoPlayer
    |
    +-- VideoContainer
    | +-- VideoElement
    | +-- SubtitleOverlay
    | +-- BufferingSpinner
    |
    +-- Controls
    | +-- ProgressBar
    | | +-- BufferedIndicator
    | | +-- PlayedIndicator
    | | +-- SeekPreview
    | | +-- ChapterMarkers
    | +-- LeftControls
    | | +-- PlayPauseButton
    | | +-- VolumeControl
    | | +-- TimeDisplay
    | +-- RightControls
    | +-- SubtitleButton
    | +-- SettingsMenu
    | +-- TheaterButton
    | +-- PiPButton
    | +-- FullscreenButton
    |
    +-- SettingsPanel
    +-- QualitySelector
    +-- SpeedSelector
    +-- SubtitleSelector

    ๐Ÿ“Œ๐ŸŽค Interviewer: "How do you implement adaptive bitrate streaming?"

    Candidate: "Use HLS.js or dash.js for ABR..."

    import Hls from 'hls.js';
    const useAdaptiveStreaming = (videoRef, manifestUrl) => {
    const [quality, setQuality] = useState('auto');
    const [availableQualities, setAvailableQualities] = useState([]);
    const hlsRef = useRef(null);
    useEffect(() => {
    const video = videoRef.current;
    if (Hls.isSupported()) {
    const hls = new Hls({
    enableWorker: true,
    lowLatencyMode: false,
    backBufferLength: 90,
    maxBufferLength: 30,
    maxMaxBufferLength: 600
    });
    hlsRef.current = hls;
    hls.loadSource(manifestUrl);
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED, (event, data) => {
    const qualities = data.levels.map((level, index) => ({
    index,
    height: level.height,
    bitrate: level.bitrate,
    label: `${level.height}p`
    }));
    setAvailableQualities([{ index: -1, label: 'Auto' }, ...qualities]);
    });
    // Monitor quality switches
    hls.on(Hls.Events.LEVEL_SWITCHED, (event, data) => {
    console.log('Quality switched to:', data.level);
    });
    return () => hls.destroy();
    } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    // Native HLS (Safari)
    video.src = manifestUrl;
    }
    }, [manifestUrl]);
    const setQualityLevel = (levelIndex) => {
    if (hlsRef.current) {
    hlsRef.current.currentLevel = levelIndex; // -1 for auto
    setQuality(levelIndex === -1 ? 'auto' : levelIndex);
    }
    };
    return { quality, availableQualities, setQualityLevel };
    };

    ๐Ÿ“Œ๐ŸŽค Interviewer: "How do you handle keyboard shortcuts?"

    Candidate:

    const useKeyboardShortcuts = (videoRef, playerState) => {
    useEffect(() => {
    const handleKeyDown = (e) => {
    // Don't trigger if typing in input
    if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
    return;
    }
    const video = videoRef.current;
    switch (e.key.toLowerCase()) {
    case ' ':
    case 'k':
    e.preventDefault();
    video.paused ? video.play() : video.pause();
    break;
    case 'f':
    e.preventDefault();
    toggleFullscreen();
    break;
    case 'm':
    e.preventDefault();
    video.muted = !video.muted;
    break;
    case 'arrowleft':
    case 'j':
    e.preventDefault();
    video.currentTime -= e.key === 'j' ? 10 : 5;
    break;
    case 'arrowright':
    case 'l':
    e.preventDefault();
    video.currentTime += e.key === 'l' ? 10 : 5;
    break;
    case 'arrowup':
    e.preventDefault();
    video.volume = Math.min(1, video.volume + 0.1);
    break;
    case 'arrowdown':
    e.preventDefault();
    video.volume = Math.max(0, video.volume - 0.1);
    break;
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    e.preventDefault();
    const percent = parseInt(e.key) * 10;
    video.currentTime = (percent / 100) * video.duration;
    break;
    case '>':
    e.preventDefault();
    video.playbackRate = Math.min(2, video.playbackRate + 0.25);
    break;
    case '<':
    e.preventDefault();
    video.playbackRate = Math.max(0.25, video.playbackRate - 0.25);
    break;
    case 'c':
    e.preventDefault();
    toggleSubtitles();
    break;
    }
    };
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
    }, []);
    };

    ๐Ÿ“Œ๐ŸŽค Interviewer: "What edge cases do you handle?"

    Candidate:

    1. Buffering & Stalling

    video.addEventListener('waiting', () => setIsBuffering(true));
    video.addEventListener('playing', () => setIsBuffering(false));
    // Detect stalls
    let lastPlayPos = 0;
    let currentPlayPos = 0;
    let bufferingDetected = false;
    setInterval(() => {
    currentPlayPos = video.currentTime;
    if (!bufferingDetected && currentPlayPos === lastPlayPos && !video.paused) {
    bufferingDetected = true;
    setIsBuffering(true);
    }
    if (bufferingDetected && currentPlayPos !== lastPlayPos) {
    bufferingDetected = false;
    setIsBuffering(false);
    }
    lastPlayPos = currentPlayPos;
    }, 100);

    2. Error Recovery

    video.addEventListener('error', (e) => {
    const error = e.target.error;
    switch (error.code) {
    case MediaError.MEDIA_ERR_NETWORK:
    // Retry with backoff
    retryWithBackoff();
    break;
    case MediaError.MEDIA_ERR_DECODE:
    // Try lower quality
    switchToLowerQuality();
    break;
    case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
    showError('Video format not supported');
    break;
    }
    });

    3. Fullscreen Compatibility

    const toggleFullscreen = () => {
    const container = playerRef.current;
    if (!document.fullscreenElement) {
    if (container.requestFullscreen) {
    container.requestFullscreen();
    } else if (container.webkitRequestFullscreen) {
    container.webkitRequestFullscreen();
    } else if (container.msRequestFullscreen) {
    container.msRequestFullscreen();
    }
    } else {
    document.exitFullscreen?.() ||
    document.webkitExitFullscreen?.() ||
    document.msExitFullscreen?.();
    }
    };

    4. Resume Playback

    // Save position
    video.addEventListener('timeupdate', () => {
    localStorage.setItem(`video-${videoId}`, video.currentTime);
    });
    // Resume on load
    useEffect(() => {
    const savedTime = localStorage.getItem(`video-${videoId}`);
    if (savedTime && parseFloat(savedTime) > 5) {
    video.currentTime = parseFloat(savedTime);
    toast('Resuming from where you left off');
    }
    }, [videoId]);

    ๐Ÿ“Œ๐Ÿ“Š Interview Scoring

    CriteriaScore

    Component Designโœ… Adaptive Streamingโœ… Keyboard Shortcutsโœ… Edge Casesโœ… Browser Compatibilityโœ…

    Result: Strong Hire ๐ŸŽ‰

    RK

    Written by

    Rohit Kumar

    Senior Engineer at YouTube

    ๐Ÿš€ Master Interview Prep

    Join 500+ developers

    Explore Courses โ†’
    Chat on WhatsApp