我想将视频流式传输到网站,以便用户不必等待整个视频加载,但我遇到了一个错误:Video Player.jsx:34 GET http://localhost:3001/public /test/output.m3u8(未找到) 我做的一切都是对的,但我无法回避这个问题。请帮忙,我的代码应该将视频分成几部分,然后必须播放它。
videoplayer.jsx
import React, { useEffect, useRef, useState } from 'react';
import Hls from 'hls.js';
const VideoPlayer = () => {
const videoRef = useRef(null);
const [videoUrl, setVideoUrl] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchVideo = async () => {
try {
const response = await fetch('http://localhost:3001/');
if (!response.ok) {
throw new Error(`Сервер вернул статус: ${response.status}`);
}
// Установите URL для HLS
setVideoUrl('http://localhost:3001/public/test/output.m3u8');
} catch (error) {
console.error('Ошибка при получении видео:', error);
} finally {
setLoading(false);
}
};
fetchVideo();
}, []);
// Воспроизведение HLS
useEffect(() => {
if (videoUrl && videoRef.current) {
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(videoUrl);
hls.attachMedia(videoRef.current);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
videoRef.current.play();
});
} else if (videoRef.current.canPlayType('application/vnd.apple.mpegurl')) {
videoRef.current.src = videoUrl;
videoRef.current.addEventListener('loadedmetadata', () => {
videoRef.current.play();
});
}
}
}, [videoUrl]);
return (
<div>
{loading ? <p>Загрузка видео...</p> : (
<video ref={videoRef} controls width="640" height="360"></video>
)}
</div>
);
};
export default VideoPlayer;
转换后的.js
import express from 'express';
import cors from 'cors';
import { spawn } from 'child_process';
import fs from 'fs';
import path from 'path';
const app = express();
const PORT = 3001;
app.use(cors());
app.get('/test-file', (req, res) => {
const testFilePath = path.join('C:/Users/fomic/vite-project/public/test/test.txt');
fs.readFile(testFilePath, 'utf8', (err, data) => {
if (err) {
console.error('Ошибка при чтении файла:', err);
return res.status(500).send('Ошибка при чтении файла.');
}
res.send(data);
});
});
app.get('/', (req, res) => {
const inputVideo = path.join('C:/Users/fomic/vite-project/public/videoplayback.mp4');
const outputPlaylist = path.join('C:/Users/fomic/vite-project/public/test/output.m3u8');
console.log('Проверка входного файла:', inputVideo);
if (!fs.existsSync(inputVideo)) {
console.error('Ошибка: входной файл не найден.');
return res.status(404).send('Входной файл не найден.');
}
// Проверка существования входного файла
console.log('Проверка входного файла:', inputVideo);
if (!fs.existsSync(inputVideo)) {
console.error('Ошибка: входной файл не найден.');
return res.status(404).send('Входной файл не найден.');
}
// Проверка существования выходной директории
const outputDir = path.dirname(outputPlaylist);
console.log('Проверка директории для выходных файлов:', outputDir);
if (!fs.existsSync(outputDir)) {
console.log('Директория не найдена. Создаю новую директорию...');
fs.mkdirSync(outputDir, { recursive: true });
}
console.log('Запуск FFmpeg для конвертации...');
const ffmpegProcess = spawn('ffmpeg', [
'-i', inputVideo,
'-c', 'copy', // Исправлено здесь
'-start_number', '0',
'-hls_time', '10',
'-hls_list_size', '0',
'-f', 'hls',
outputPlaylist
]);
ffmpegProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ffmpegProcess.stderr.on('data', (data) => {
console.error(`stderr: ${data.toString()}`);
});
ffmpegProcess.on('close', (code) => {
if (code === 0) {
res.send('Конвертация завершена!');
} else {
console.error(`Ошибка при выполнении FFmpeg, код: ${code}`);
res.status(500).send(`Ошибка при конвертации видео, код: ${code}`);
}
});
});
// Запуск сервера
app.listen(PORT, () => {
console.log(`Сервер запущен на http://localhost:${PORT}`);
});
app.jsx
import { useState } from 'react'
import Release from './components/Release/Release'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import Header from './components/Header/Header'
import Podcaster from './components/Podcaster/Podcaster'
import TabsSection from './components/TabsSection/TabsSection'
import LentaSection from './components/LentaSection/LentaSection'
import SubscribesSection from './components/SubscribesSection/SubscribesSection'
import PlayListSection from './components/PlayListSection/PlayListSection'
import { Registration } from './components/Forms/Registration'
import { Auth } from './components/Forms/Aurh'
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
function App() {
const [count, setCount] = useState(0)
return (
<>
<Router>
<Header/>
<Routes>
<Route path="/auth" element={<Auth />} />
<Route path="/release" element={<Release />} />
<Route path="/podcaster" element={<Podcaster />} />
</Routes>
</Router>
</>
)
}
export default App
确保您的 Express 服务器配置为提供静态文件 在您的服务器代码中添加此行
app.use('/public',express.static(path.join(__dirname,'public')));
这将允许您的服务器从公共目录正确提供 .m3u8 和视频文件
确保您的 VideoPlayer.jsx 正在获取正确的视频 URL
setVideoUrl('http://localhost:3001/public/test/output.m3u8');
此 URL 应与服务器提供 .m3u8 文件的路径匹配