使用 JavaScript,我尝试接收视频块并将它们显示在 html 视频标签中。但在我的代码中,显示 3 或 4 个块后,它会卡住并且不会移动到下一个块。 你能帮我吗?
// Fetch an encrypted video chunk from the server
async function fetchChunk(chunkIndex) {
const url = `http://localhost/video/encrypted_chunks/chunk_${chunkIndex}.enc`;
try {
const response = await fetch(url);
if (response.ok) {
return await response.arrayBuffer();
} else {
console.error(`Failed to fetch chunk ${chunkIndex}: Status ${response.status}`);
return null;
}
} catch (error) {
console.error(`Error fetching chunk ${chunkIndex}:`, error);
return null;
}
}
function appendBuffer(sourceBuffer, decryptedData) {
return new Promise((resolve, reject) => {
function onUpdateEnd() {
sourceBuffer.removeEventListener('updateend', onUpdateEnd);
resolve();
}
if (sourceBuffer.updating) {
sourceBuffer.addEventListener('updateend', onUpdateEnd, { once: true });
} else {
sourceBuffer.appendBuffer(new Uint8Array(decryptedData));
resolve();
}
});
}
// Finalize the MediaSource stream
function finalizeStream(mediaSource) {
if (mediaSource.readyState === 'open') {
mediaSource.endOfStream();
}
}
// Main function to handle video streaming
async function streamVideo() {
const mediaSource = new MediaSource();
const video = document.getElementById('videoPlayer');
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', async () => {
const sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8, vorbis"');
let chunkIndex = 1;
const filename = 'sample-2.webm'; // Replace with the actual filename
const { key, iv } = await calculateKeyIv(filename);
// Function to handle fetching, decrypting, and appending chunks
async function handleChunks() {
try {
while (true) {
if (sourceBuffer.updating) {
await new Promise(resolve => sourceBuffer.addEventListener('updateend', resolve, { once: true }));
}
const encryptedData = await fetchChunk(chunkIndex);
if (!encryptedData) break; // No more data
const decryptedData = await decryptChunk(encryptedData, key, iv);
await appendBuffer(sourceBuffer, decryptedData);
chunkIndex++;
}
// Wait for buffer to be done updating before finalizing
if (!sourceBuffer.updating) {
finalizeStream(mediaSource);
createWatermark();
}
} catch (error) {
console.error('Error processing chunks:', error);
}
}
// Start processing chunks
handleChunks();
});
}
// Call the streamVideo function to start streaming
streamVideo();
我认为问题可能出在缓冲区上,但我是 JavaScript 新手,我无法调试它!
看起来您在流媒体视频块方面走在正确的轨道上,但可能需要考虑一些可能导致您的问题的事情。根据您的代码,这里有一些建议来解决显示几个块后卡住的问题: 检查 sourceBuffer 状态:确保 sourceBuffer 未更新或尚未处于可能阻止附加新数据的状态。 正确处理 updateend:确保正确处理 updateend 事件以避免潜在的竞争情况。如果缓冲区更新尚未完成,则在循环内添加事件侦听器可能会产生问题。 谨慎使用 sourceBuffer.remove():如果您在代码中使用 sourceBuffer.remove() (代码片段中未显示),请小心,因为它可能会导致冲突。 确保decryptChunk正确:验证decryptChunk函数是否正常运行并且没有引入任何错误。
// Fetch an encrypted video chunk from the server
async function fetchChunk(chunkIndex) {
const url = `http://localhost/video/encrypted_chunks/chunk_${chunkIndex}.enc`;
try {
const response = await fetch(url);
if (response.ok) {
return await response.arrayBuffer();
} else {
console.error(`Failed to fetch chunk ${chunkIndex}: Status ${response.status}`);
return null;
}
} catch (error) {
console.error(`Error fetching chunk ${chunkIndex}:`, error);
return null;
}
}
function appendBuffer(sourceBuffer, decryptedData) {
return new Promise((resolve, reject) => {
function onUpdateEnd() {
sourceBuffer.removeEventListener('updateend', onUpdateEnd);
resolve();
}
if (sourceBuffer.updating) {
sourceBuffer.addEventListener('updateend', onUpdateEnd, { once: true });
} else {
sourceBuffer.appendBuffer(new Uint8Array(decryptedData));
resolve();
}
});
}
// Finalize the MediaSource stream
function finalizeStream(mediaSource) {
if (mediaSource.readyState === 'open') {
mediaSource.endOfStream();
}
}
// Main function to handle video streaming
async function streamVideo() {
const mediaSource = new MediaSource();
const video = document.getElementById('videoPlayer');
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', async () => {
const sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8, vorbis"');
let chunkIndex = 1;
const filename = 'sample-2.webm'; // Replace with the actual filename
const { key, iv } = await calculateKeyIv(filename);
// Function to handle fetching, decrypting, and appending chunks
async function handleChunks() {
try {
while (true) {
// Wait for sourceBuffer to be ready
if (sourceBuffer.updating) {
await new Promise(resolve => sourceBuffer.addEventListener('updateend', resolve, { once: true }));
}
const encryptedData = await fetchChunk(chunkIndex);
if (!encryptedData) break; // No more data
const decryptedData = await decryptChunk(encryptedData, key, iv);
await appendBuffer(sourceBuffer, decryptedData);
chunkIndex++;
}
// Wait for buffer to be done updating before finalizing
await new Promise(resolve => {
if (sourceBuffer.updating) {
sourceBuffer.addEventListener('updateend', resolve, { once: true });
} else {
resolve();
}
});
finalizeStream(mediaSource);
createWatermark();
} catch (error) {
console.error('Error processing chunks:', error);
}
}
// Start processing chunks
handleChunks();
});
}
// Call the streamVideo function to start streaming
streamVideo();