110 lines
3.1 KiB
TypeScript

import React, { useState, useEffect, useRef } from "react";
import Hls from "hls.js";
const API_URL = "http://localhost:8081/start"; // Replace with your actual API endpoint
const RtspStream: React.FC = () => {
const [rtspUrl, setRtspUrl] = useState<string>("");
const [cameraName, setCameraName] = useState<string>("");
const [m3u8Url, setM3u8Url] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(false); // Loading state
const videoRef = useRef<HTMLVideoElement | null>(null);
useEffect(() => {
if (m3u8Url && videoRef.current) {
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(m3u8Url);
hls.attachMedia(videoRef.current);
} else if (
videoRef.current.canPlayType("application/vnd.apple.mpegurl")
) {
videoRef.current.src = m3u8Url;
}
}
}, [m3u8Url]);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true); // Set loading to true when submitting
try {
const response = await fetch(API_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
uri: rtspUrl,
alias: cameraName,
}),
});
if (!response.ok) {
throw new Error("Failed to fetch stream URL");
}
const data = await response.json();
console.log("Stream data:", data);
setM3u8Url(`http://localhost:8081${data?.uri}`);
} catch (error) {
console.error("Error fetching stream:", error);
alert("Failed to load stream.");
} finally {
setLoading(false); // Reset loading state after API response
}
};
return (
<div style={{ maxWidth: "600px", margin: "auto", textAlign: "center" }}>
<h2>RTSP Stream</h2>
<form onSubmit={handleSubmit}>
<input
type="text"
value={rtspUrl}
onChange={(e) => setRtspUrl(e.target.value)}
placeholder="Enter RTSP URL"
style={{ width: "80%", padding: "8px", marginBottom: "10px" }}
required
/>
<br />
<input
type="text"
value={cameraName}
onChange={(e) => setCameraName(e.target.value)}
placeholder="Enter Camera Name"
style={{ width: "80%", padding: "8px", marginBottom: "10px" }}
required
/>
<br />
<button
type="submit"
style={{
padding: "8px 12px",
cursor: loading ? "not-allowed" : "pointer",
opacity: loading ? 0.6 : 1,
}}
disabled={loading}
>
{loading ? "Starting stream..." : "Start Stream"}
</button>
</form>
{loading && (
<p style={{ marginTop: "15px", fontWeight: "bold" }}>
Stream is starting...
</p>
)}
{m3u8Url && !loading && (
<video
ref={videoRef}
controls
autoPlay
style={{ width: "100%", marginTop: "20px" }}
/>
)}
</div>
);
};
export default RtspStream;