You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTML Video标签使用Base64作为源无法显示问题求助

问题描述

我开发了一个视频播放器项目,支持用户选择目录,程序会读取目录内所有MP4视频,左侧区域的播放器展示视频内容,右侧区域列出可选择的视频(项目布局参考:项目布局)。目前用原生JavaScript实现,已完成目录选择与视频列表展示,但点击视频名称后,页面虽生成带Base64编码源的video标签,却无任何显示(连空白播放器区域都不出现),查看Base64编码发现存在空白片段,不知道该怎么解决。


项目代码

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Video Player</title>
</head>
<body>
    <div class="select-folder-div">
        <input type="file" name="file" id="file-selector" class="file-selector" webkitdirectory multiple>
    </div>
    <div class="main-div">
        <div class="video-player-div" id="video-player-div">

        </div>
        <div class="video-chooser-div" id="video-chooser-div">
        
        </div>
    </div>
    <script src="index.js"></script>
</body>
</html>

CSS代码

body {
    background: rgb(34, 32, 32);
    color: rgb(204, 87, 204);
    font-size: 1.5em;
    font-family:'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
}

.main-div {
    display: flex;
    flex-direction: row;
}

.video-player-div{
    display: flex;
    align-items: center;
    align-self: flex-start;
    border: 5px solid rgb(204, 87, 204);
    width: 70%;
    margin-top: 5%;
    margin-bottom: 10%;
    margin-left: 3%;
    margin-right: 3%;
    padding: 3%;
}

.video-chooser-div {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 20px;
    border: 5px solid rgb(204, 87, 204);
    width: 21%;
    margin-top: 5%;
    margin-bottom: 10%;
    margin-right: 3%;
    padding: 3%;
    overflow: auto;
}

.file-selector {
    margin-left: 45%;
    margin-top: 3%;
}

.video-name:hover {
    cursor: pointer;
    color: blueviolet;
}

.video-name:active {
    color: rgb(99, 14, 178);
}

JavaScript代码

const directoryInput = document.getElementById("file-selector");
const videoChooser = document.getElementById("video-chooser-div");
const videoPlayer = document.getElementById("video-player-div");

directoryInput.addEventListener("change", (event) => {
    videoChooser.innerHTML = "";

    for (const file of event.target.files) {
        if (file.name.endsWith(".mp4")) {
            let videoContentDiv = document.createElement("div");
            videoContentDiv.className = "video-content";

            let videoName = file.name;
            let videoNameTag = document.createElement("p");
            videoNameTag.className = "video-name";
            videoNameTag.textContent = videoName;

            videoContentDiv.appendChild(videoNameTag);

            videoChooser.appendChild(videoContentDiv);

            videoContentDiv.addEventListener("click", () => {
                videoPlayer.innerHTML = "";

                const video = document.createElement("video");

                const reader = new FileReader();
                reader.onload = (event) => {
                    video.src = event.target.result;
                    console.log(video.src)
                };
                reader.readAsDataURL(file); 
            
                video.width = "100%";
                video.controls = true;

                videoPlayer.appendChild(video);
            });
        }
    }
}, false);

解决方案

核心问题

用FileReader.readAsDataURL处理视频文件会生成超长Base64字符串,不仅加载效率低,还容易因内存溢出导致渲染异常;另外video标签缺少必要的样式适配,无法正常占据容器空间。

修复步骤

  1. 替换Base64方案为本地临时URL
    放弃FileReader,改用URL.createObjectURL生成视频文件的临时访问地址,这是浏览器处理本地文件的高效方式,不会产生超长Base64字符串。同时要记得释放旧视频的URL资源,避免内存泄漏。

  2. 添加video标签样式适配
    给video标签设置块级显示和自适应尺寸,确保它能正确填充播放器容器。

修复后的完整JavaScript代码

const directoryInput = document.getElementById("file-selector");
const videoChooser = document.getElementById("video-chooser-div");
const videoPlayer = document.getElementById("video-player-div");

directoryInput.addEventListener("change", (event) => {
    videoChooser.innerHTML = "";

    for (const file of event.target.files) {
        if (file.name.endsWith(".mp4")) {
            let videoContentDiv = document.createElement("div");
            videoContentDiv.className = "video-content";

            let videoName = file.name;
            let videoNameTag = document.createElement("p");
            videoNameTag.className = "video-name";
            videoNameTag.textContent = videoName;

            videoContentDiv.appendChild(videoNameTag);
            videoChooser.appendChild(videoContentDiv);

            videoContentDiv.addEventListener("click", () => {
                // 释放旧视频的URL资源
                const oldVideo = videoPlayer.querySelector('video');
                if (oldVideo) {
                    URL.revokeObjectURL(oldVideo.src);
                }
                videoPlayer.innerHTML = "";

                const video = document.createElement("video");
                // 使用createObjectURL替代FileReader
                video.src = URL.createObjectURL(file);
                video.controls = true;
                // 设置video样式确保正常显示
                video.style.display = "block";
                video.style.width = "100%";
                video.style.height = "auto";

                videoPlayer.appendChild(video);
            });
        }
    }
}, false);

额外优化建议

  • 目录选择器添加directory属性,提升浏览器兼容性:
    <input type="file" name="file" id="file-selector" class="file-selector" directory webkitdirectory multiple>
    
  • 给选中的视频列表项添加高亮样式,提升用户体验:
    .video-content.active .video-name {
        color: rgb(99, 14, 178);
    }
    
    然后在点击事件中添加选中状态切换逻辑:
    // 点击事件内添加
    document.querySelectorAll('.video-content').forEach(item => item.classList.remove('active'));
    videoContentDiv.classList.add('active');
    

内容的提问来源于stack exchange,提问作者Sisifos496

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 01:00:39