|
1875 | 1875 |
|
1876 | 1876 | // Play button click events |
1877 | 1877 | playButton.addEventListener('click', function() { |
1878 | | - if (frameVideo.paused) { |
1879 | | - frameVideo.play(); |
| 1878 | + // Priority load full video when play button is clicked |
| 1879 | + if (frameVideo.readyState < 2) { |
| 1880 | + // Video not ready yet, prioritize loading |
| 1881 | + console.log('🚀 Priority loading frameVideo for playback...'); |
| 1882 | + frameVideo.preload = 'auto'; |
| 1883 | + frameVideo.setAttribute('fetchpriority', 'high'); |
| 1884 | + |
| 1885 | + // Pause other videos to free up bandwidth for frameVideo |
| 1886 | + document.querySelectorAll('video:not(#frameVideo):not(#hero-video-main):not(#hero-video-mobile)').forEach(video => { |
| 1887 | + if (!video.paused) { |
| 1888 | + video.pause(); |
| 1889 | + } |
| 1890 | + // Reduce priority of other videos |
| 1891 | + if (video.preload === 'auto') { |
| 1892 | + video.preload = 'metadata'; |
| 1893 | + } |
| 1894 | + }); |
| 1895 | + |
| 1896 | + // Restore src if it was blocked |
| 1897 | + if (frameVideo.hasAttribute('data-temp-src') && !frameVideo.src) { |
| 1898 | + frameVideo.src = frameVideo.getAttribute('data-temp-src'); |
| 1899 | + frameVideo.removeAttribute('data-temp-src'); |
| 1900 | + } |
| 1901 | + const frameSource = frameVideo.querySelector('source'); |
| 1902 | + if (frameSource && frameSource.hasAttribute('data-temp-src') && !frameSource.src) { |
| 1903 | + frameSource.src = frameSource.getAttribute('data-temp-src'); |
| 1904 | + frameSource.removeAttribute('data-temp-src'); |
| 1905 | + } |
| 1906 | + |
| 1907 | + // Force load with high priority |
| 1908 | + frameVideo.load(); |
| 1909 | + |
| 1910 | + // Wait for video to be ready before playing |
| 1911 | + frameVideo.addEventListener('canplay', function playWhenReady() { |
| 1912 | + frameVideo.removeEventListener('canplay', playWhenReady); |
| 1913 | + frameVideo.play().catch(err => { |
| 1914 | + console.log('Play failed, trying again:', err); |
| 1915 | + setTimeout(() => frameVideo.play(), 100); |
| 1916 | + }); |
| 1917 | + playButton.className = 'play-button playing'; |
| 1918 | + playButton.title = 'Pause'; |
| 1919 | + }, { once: true }); |
| 1920 | + } else if (frameVideo.paused) { |
| 1921 | + // Video is ready, just play |
| 1922 | + frameVideo.play().catch(err => { |
| 1923 | + console.log('Play failed:', err); |
| 1924 | + }); |
1880 | 1925 | this.className = 'play-button playing'; |
1881 | 1926 | this.title = 'Pause'; |
1882 | 1927 | } else { |
| 1928 | + // Video is playing, pause it |
1883 | 1929 | frameVideo.pause(); |
1884 | 1930 | this.className = 'play-button paused'; |
1885 | 1931 | this.title = 'Play'; |
|
2637 | 2683 | waitForHeroVideo(() => { |
2638 | 2684 | console.log('🎬 Hero video loaded! Starting to load other videos...'); |
2639 | 2685 |
|
2640 | | - // Restore frameVideo immediately when hero video is loaded (it's in viewport) |
| 2686 | + // Restore frameVideo when hero video is loaded (preload="metadata" only) |
2641 | 2687 | const frameVideo = document.getElementById('frameVideo'); |
2642 | 2688 | if (frameVideo) { |
| 2689 | + // Only restore src, keep preload as metadata (will upgrade to auto when play button is clicked) |
2643 | 2690 | if (frameVideo.hasAttribute('data-temp-src') && !frameVideo.src) { |
2644 | 2691 | frameVideo.src = frameVideo.getAttribute('data-temp-src'); |
2645 | 2692 | frameVideo.removeAttribute('data-temp-src'); |
| 2693 | + frameVideo.preload = 'metadata'; // Keep as metadata |
2646 | 2694 | frameVideo.load(); |
2647 | 2695 | } |
2648 | 2696 | const frameSource = frameVideo.querySelector('source'); |
2649 | 2697 | if (frameSource && frameSource.hasAttribute('data-temp-src') && !frameSource.src) { |
2650 | 2698 | frameSource.src = frameSource.getAttribute('data-temp-src'); |
2651 | 2699 | frameSource.removeAttribute('data-temp-src'); |
| 2700 | + frameVideo.preload = 'metadata'; // Keep as metadata |
2652 | 2701 | frameVideo.load(); |
2653 | 2702 | } |
2654 | 2703 | } |
|
2749 | 2798 | if (video.id !== 'hero-video-main' && video.id !== 'hero-video-mobile') { |
2750 | 2799 | videoObserver.observe(video); |
2751 | 2800 |
|
2752 | | - // If it's frameVideo, ensure it's loaded immediately (it's in viewport) |
| 2801 | + // If it's frameVideo, restore src but keep preload as metadata |
2753 | 2802 | if (video.id === 'frameVideo') { |
2754 | 2803 | // Restore src if it was blocked |
2755 | 2804 | if (video.hasAttribute('data-temp-src') && !video.src) { |
2756 | 2805 | video.src = video.getAttribute('data-temp-src'); |
2757 | 2806 | video.removeAttribute('data-temp-src'); |
| 2807 | + video.preload = 'metadata'; // Keep as metadata |
2758 | 2808 | video.load(); |
2759 | 2809 | } |
2760 | 2810 | const source = video.querySelector('source'); |
2761 | 2811 | if (source && source.hasAttribute('data-temp-src') && !source.src) { |
2762 | 2812 | source.src = source.getAttribute('data-temp-src'); |
2763 | 2813 | source.removeAttribute('data-temp-src'); |
| 2814 | + video.preload = 'metadata'; // Keep as metadata |
2764 | 2815 | video.load(); |
2765 | 2816 | } |
2766 | 2817 | } |
2767 | 2818 | } |
2768 | 2819 | }); |
| 2820 | + |
| 2821 | + // Preload basic locomotion videos when reward-optimization section comes into view |
| 2822 | + const rewardOptimizationSection = document.getElementById('reward-optimization'); |
| 2823 | + if (rewardOptimizationSection) { |
| 2824 | + const sectionObserver = new IntersectionObserver((entries) => { |
| 2825 | + entries.forEach(entry => { |
| 2826 | + if (entry.isIntersecting && window.heroVideoLoaded) { |
| 2827 | + console.log('🎯 Reward Optimization section in view - preloading basic locomotion videos...'); |
| 2828 | + |
| 2829 | + // Find all locomotion videos in basic-locomotion tab |
| 2830 | + const basicLocomotionVideos = rewardOptimizationSection.querySelectorAll('#basic-locomotion video'); |
| 2831 | + basicLocomotionVideos.forEach((video, index) => { |
| 2832 | + // Restore src if it was blocked |
| 2833 | + if (video.hasAttribute('data-temp-src') && !video.src) { |
| 2834 | + video.src = video.getAttribute('data-temp-src'); |
| 2835 | + video.removeAttribute('data-temp-src'); |
| 2836 | + } |
| 2837 | + const source = video.querySelector('source'); |
| 2838 | + if (source && source.hasAttribute('data-temp-src') && !source.src) { |
| 2839 | + source.src = source.getAttribute('data-temp-src'); |
| 2840 | + source.removeAttribute('data-temp-src'); |
| 2841 | + } |
| 2842 | + |
| 2843 | + // Set preload to metadata first, then auto after a delay |
| 2844 | + setTimeout(() => { |
| 2845 | + if (video.preload === 'none') { |
| 2846 | + video.preload = 'metadata'; |
| 2847 | + video.load(); |
| 2848 | + } |
| 2849 | + // Upgrade to auto preload after metadata loads |
| 2850 | + setTimeout(() => { |
| 2851 | + if (video.readyState >= 1) { |
| 2852 | + video.preload = 'auto'; |
| 2853 | + video.load(); |
| 2854 | + } |
| 2855 | + }, 500); |
| 2856 | + }, index * 200); // Stagger loading by 200ms per video |
| 2857 | + }); |
| 2858 | + |
| 2859 | + // Unobserve after loading starts |
| 2860 | + sectionObserver.unobserve(entry.target); |
| 2861 | + } |
| 2862 | + }); |
| 2863 | + }, { |
| 2864 | + rootMargin: '300px' // Start loading when section is 300px away |
| 2865 | + }); |
| 2866 | + |
| 2867 | + sectionObserver.observe(rewardOptimizationSection); |
| 2868 | + } |
2769 | 2869 |
|
2770 | 2870 | // Smart auto-play system for all gallery videos with optimized loading |
2771 | 2871 | function initializeGalleryAutoPlay() { |
@@ -3580,7 +3680,7 @@ <h4 style="text-align: center; margin-bottom: 15px; font-family: var(--font-sans |
3580 | 3680 |
|
3581 | 3681 | <!-- Main video (for frame-by-frame viewing) --> |
3582 | 3682 | <div class="column has-text-centered"> |
3583 | | - <video id="frameVideo" width="90%" height="auto" muted playsinline style="border: 1px solid #bbb; border-radius: 10px; margin: 1.0%;"> |
| 3683 | + <video id="frameVideo" width="90%" height="auto" muted playsinline preload="metadata" style="border: 1px solid #bbb; border-radius: 10px; margin: 1.0%;"> |
3584 | 3684 | <source src="./resources/goal_reaching/full/full-2_firefox_720p.mp4" type="video/mp4"> |
3585 | 3685 | </video> |
3586 | 3686 | </div> |
|
0 commit comments