media-stream-player
Version:
Player built on top of media-stream-library
1,318 lines (1,279 loc) • 83.6 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/index.ts
var src_exports = {};
__export(src_exports, {
AxisApi: () => AxisApi,
BasicPlayer: () => BasicPlayer,
Container: () => Container,
FORMAT_API: () => FORMAT_API,
Format: () => Format,
Layer: () => Layer,
PlaybackArea: () => PlaybackArea,
Player: () => Player,
Protocol: () => Protocol,
Stats: () => Stats,
browserSupportedFormats: () => browserSupportedFormats,
getImageURL: () => getImageURL
});
module.exports = __toCommonJS(src_exports);
// src/MediaStreamPlayer.tsx
var import_react26 = __toESM(require("react"));
var import_client = require("react-dom/client");
// src/BasicPlayer.tsx
var import_react21 = __toESM(require("react"));
// src/Container.tsx
var import_react = __toESM(require("react"));
var import_styled_components = __toESM(require("styled-components"));
var DEFAULT_ASPECT_RATIO = 16 / 9;
var getHeightPct = (aspectRatio) => {
if (aspectRatio === 0) {
throw new Error("Cannot handle aspect ratio 0");
}
return 100 / aspectRatio;
};
var ContainerBody = import_styled_components.default.div.attrs(
({ aspectRatio }) => {
return { style: { paddingTop: `${getHeightPct(aspectRatio)}%` } };
}
)`
width: 100%;
background: black;
position: relative;
`;
var Layer = import_styled_components.default.div`
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
`;
var Container = ({
aspectRatio = DEFAULT_ASPECT_RATIO,
children
}) => /* @__PURE__ */ import_react.default.createElement(ContainerBody, { aspectRatio }, children);
// src/Controls.tsx
var import_react13 = __toESM(require("react"));
var import_luxon = require("luxon");
var import_styled_components5 = __toESM(require("styled-components"));
// src/Settings.tsx
var import_react3 = __toESM(require("react"));
var import_styled_components3 = __toESM(require("styled-components"));
// src/components/Switch.tsx
var import_react2 = __toESM(require("react"));
var import_styled_components2 = __toESM(require("styled-components"));
var Container2 = import_styled_components2.default.label`
position: relative;
display: inline-block;
width: 28px;
height: 16px;
`;
var Input = import_styled_components2.default.input`
opacity: 0;
width: 0;
height: 0;
`;
var Slider = import_styled_components2.default.span`
border-radius: 16px;
cursor: pointer;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #ccc;
transition: 0.4s;
&:before {
border-radius: 50%;
content: '';
position: absolute;
height: 12px;
width: 12px;
left: 2px;
bottom: 2px;
background-color: white;
transition: 0.4s;
}
${Input}:checked + & {
background-color: #2196f3;
}
${Input}:checked + &:before {
transform: translateX(12px);
}
${Input}:focus + & {
box-shadow: 0 0 1px #2196f3;
}
`;
var Switch = (props) => {
return /* @__PURE__ */ import_react2.default.createElement(Container2, null, /* @__PURE__ */ import_react2.default.createElement(Input, __spreadValues({ type: "checkbox" }, props)), /* @__PURE__ */ import_react2.default.createElement(Slider, null));
};
// src/Settings.tsx
var SettingsMenu = import_styled_components3.default.div`
font-family: sans-serif;
display: flex;
flex-direction: column;
position: absolute;
bottom: 32px;
right: 0;
background: rgb(0, 0, 0, 0.66);
padding: 8px 16px;
margin-bottom: 16px;
margin-right: 8px;
&:after {
content: '';
width: 10px;
height: 10px;
transform: rotate(45deg);
position: absolute;
bottom: -5px;
right: 12px;
background: rgb(0, 0, 0, 0.66);
}
`;
var SettingsItem = import_styled_components3.default.div`
display: flex;
flex-direction: row;
color: white;
height: 24px;
width: 320px;
align-items: center;
justify-content: space-between;
margin: 4px 0;
`;
var Settings = ({
parameters,
format,
onFormat,
onVapix,
showStatsOverlay,
toggleStats
}) => {
const [textString, setTextString] = (0, import_react3.useState)(parameters["textstring"]);
const textStringTimeout = (0, import_react3.useRef)();
const changeParam = (0, import_react3.useCallback)(
(e) => {
const { name, value } = e.target;
switch (name) {
case "textstring":
setTextString(value);
clearTimeout(textStringTimeout.current);
textStringTimeout.current = window.setTimeout(() => {
onVapix(name, value);
}, 300);
break;
case "text":
onVapix(name, value ? "1" : "0");
break;
default:
console.warn("internal error");
}
},
[onVapix]
);
const changeStatsOverlay = (0, import_react3.useCallback)(
(e) => toggleStats(e.target.checked),
[toggleStats]
);
const changeFormat = (0, import_react3.useCallback)(
(e) => onFormat(e.target.value),
[onFormat]
);
const changeResolution = (0, import_react3.useCallback)(
(e) => onVapix("resolution", e.target.value),
[onVapix]
);
const changeRotation = (0, import_react3.useCallback)(
(e) => onVapix("rotation", e.target.value),
[onVapix]
);
const changeCompression = (0, import_react3.useCallback)(
(e) => onVapix("compression", e.target.value),
[onVapix]
);
return /* @__PURE__ */ import_react3.default.createElement(SettingsMenu, null, /* @__PURE__ */ import_react3.default.createElement(SettingsItem, null, /* @__PURE__ */ import_react3.default.createElement("div", null, "Format"), /* @__PURE__ */ import_react3.default.createElement("select", { onChange: changeFormat, defaultValue: format }, /* @__PURE__ */ import_react3.default.createElement("option", { value: "RTP_H264" }, "H.264 (RTP over WS)"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "MP4_H264" }, "H.264 (MP4 over HTTP)"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "RTP_JPEG" }, "Motion JPEG"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "JPEG" }, "Still image"))), /* @__PURE__ */ import_react3.default.createElement(SettingsItem, null, /* @__PURE__ */ import_react3.default.createElement("div", null, "Resolution"), /* @__PURE__ */ import_react3.default.createElement("select", { value: parameters["resolution"], onChange: changeResolution }, /* @__PURE__ */ import_react3.default.createElement("option", { value: "" }, "default"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "1920x1080" }, "1920 x 1080 (FHD)"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "1280x720" }, "1280 x 720 (HD)"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "800x600" }, "800 x 600 (VGA)"))), /* @__PURE__ */ import_react3.default.createElement(SettingsItem, null, /* @__PURE__ */ import_react3.default.createElement("div", null, "Rotation"), /* @__PURE__ */ import_react3.default.createElement("select", { value: parameters["rotation"], onChange: changeRotation }, /* @__PURE__ */ import_react3.default.createElement("option", { value: "0" }, "0"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "90" }, "90"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "180" }, "180"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "270" }, "270"))), /* @__PURE__ */ import_react3.default.createElement(SettingsItem, null, /* @__PURE__ */ import_react3.default.createElement("div", null, "Compression"), /* @__PURE__ */ import_react3.default.createElement("select", { value: parameters["compression"], onChange: changeCompression }, /* @__PURE__ */ import_react3.default.createElement("option", { value: "" }, "default"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "0" }, "0"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "10" }, "10"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "20" }, "20"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "30" }, "30"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "40" }, "40"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "50" }, "50"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "60" }, "60"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "70" }, "70"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "80" }, "80"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "90" }, "90"), /* @__PURE__ */ import_react3.default.createElement("option", { value: "100" }, "100"))), /* @__PURE__ */ import_react3.default.createElement(SettingsItem, null, /* @__PURE__ */ import_react3.default.createElement("div", null, "Text overlay"), /* @__PURE__ */ import_react3.default.createElement("input", { name: "textstring", value: textString, onChange: changeParam }), /* @__PURE__ */ import_react3.default.createElement(
Switch,
{
name: "text",
checked: parameters["text"] === "1",
onChange: changeParam
}
)), /* @__PURE__ */ import_react3.default.createElement(SettingsItem, null, /* @__PURE__ */ import_react3.default.createElement("div", null, "Stats overlay"), /* @__PURE__ */ import_react3.default.createElement(Switch, { checked: showStatsOverlay, onChange: changeStatsOverlay })));
};
// src/components/Button.tsx
var import_styled_components4 = __toESM(require("styled-components"));
var Button = import_styled_components4.default.button`
background: transparent;
fill: white;
border: none;
box-sizing: border-box;
padding: 0;
margin: 0;
line-height: 0;
:focus {
outline: none;
}
`;
// src/hooks/useUserActive.ts
var import_react4 = require("react");
var DEFAULT_TIMEOUT = 3e3;
var useUserActive = (ref, duration = DEFAULT_TIMEOUT) => {
const [userActive, setUserActive] = (0, import_react4.useState)(false);
const startUserActive = () => setUserActive(true);
const stopUserActive = () => setUserActive(false);
(0, import_react4.useEffect)(() => {
if (userActive) {
const timer = setTimeout(stopUserActive, duration);
return () => {
clearTimeout(timer);
};
}
});
(0, import_react4.useEffect)(() => {
const el = ref.current;
if (el === null) {
return;
}
el.addEventListener("pointermove", startUserActive);
if (userActive) {
el.addEventListener("pointerleave", stopUserActive);
}
return () => {
el.removeEventListener("pointermove", startUserActive);
if (userActive) {
el.removeEventListener("pointerleave", stopUserActive);
}
};
}, [userActive, ref]);
return userActive;
};
// src/img/CogWheel.tsx
var import_react5 = __toESM(require("react"));
var CogWheel = ({ title }) => {
return /* @__PURE__ */ import_react5.default.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "20",
height: "20",
viewBox: "0 0 20 20"
},
title !== void 0 ? /* @__PURE__ */ import_react5.default.createElement("title", null, title) : null,
/* @__PURE__ */ import_react5.default.createElement("path", { fill: "none", d: "M0 0h20v20H0V0z" }),
/* @__PURE__ */ import_react5.default.createElement("path", { d: "M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z" })
);
};
// src/img/Pause.tsx
var import_react6 = __toESM(require("react"));
var Pause = ({ title }) => {
return /* @__PURE__ */ import_react6.default.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "24",
height: "24",
viewBox: "0 0 24 24"
},
title !== void 0 ? /* @__PURE__ */ import_react6.default.createElement("title", null, title) : null,
/* @__PURE__ */ import_react6.default.createElement("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" }),
/* @__PURE__ */ import_react6.default.createElement("path", { d: "M0 0h24v24H0z", fill: "none" })
);
};
// src/img/Play.tsx
var import_react7 = __toESM(require("react"));
var Play = ({ title }) => {
return /* @__PURE__ */ import_react7.default.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "24",
height: "24",
viewBox: "0 0 24 24"
},
title !== void 0 ? /* @__PURE__ */ import_react7.default.createElement("title", null, title) : null,
/* @__PURE__ */ import_react7.default.createElement("path", { d: "M8 5v14l11-7z" }),
/* @__PURE__ */ import_react7.default.createElement("path", { d: "M0 0h24v24H0z", fill: "none" })
);
};
// src/img/Refresh.tsx
var import_react8 = __toESM(require("react"));
var Refresh = ({ title }) => {
return /* @__PURE__ */ import_react8.default.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
height: "24",
viewBox: "0 0 24 24",
width: "24"
},
title !== void 0 ? /* @__PURE__ */ import_react8.default.createElement("title", null, title) : null,
/* @__PURE__ */ import_react8.default.createElement("path", { d: "M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" }),
/* @__PURE__ */ import_react8.default.createElement("path", { d: "M0 0h24v24H0z", fill: "none" })
);
};
// src/img/Screenshot.tsx
var import_react9 = __toESM(require("react"));
var Screenshot = ({ title }) => {
return /* @__PURE__ */ import_react9.default.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "24",
height: "24",
viewBox: "0 0 24 24"
},
title !== void 0 ? /* @__PURE__ */ import_react9.default.createElement("title", null, title) : null,
/* @__PURE__ */ import_react9.default.createElement("path", { d: "M0 0h24v24H0z", fill: "none" }),
/* @__PURE__ */ import_react9.default.createElement("circle", { cx: "12", cy: "12", r: "3.2" }),
/* @__PURE__ */ import_react9.default.createElement("path", { d: "M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" })
);
};
// src/img/Spinner.tsx
var import_react10 = __toESM(require("react"));
var Spinner = () => {
return /* @__PURE__ */ import_react10.default.createElement(
"svg",
{
width: "38",
height: "38",
viewBox: "0 0 38 38",
xmlns: "http://www.w3.org/2000/svg"
},
/* @__PURE__ */ import_react10.default.createElement("defs", null, /* @__PURE__ */ import_react10.default.createElement("linearGradient", { x1: "8.042%", y1: "0%", x2: "65.682%", y2: "23.865%", id: "a" }, /* @__PURE__ */ import_react10.default.createElement("stop", { stopColor: "#fff", stopOpacity: "0", offset: "0%" }), /* @__PURE__ */ import_react10.default.createElement("stop", { stopColor: "#fff", stopOpacity: ".631", offset: "63.146%" }), /* @__PURE__ */ import_react10.default.createElement("stop", { stopColor: "#fff", offset: "100%" }))),
/* @__PURE__ */ import_react10.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react10.default.createElement("g", { transform: "translate(1 1)" }, /* @__PURE__ */ import_react10.default.createElement(
"path",
{
d: "M36 18c0-9.94-8.06-18-18-18",
id: "Oval-2",
stroke: "url(#a)",
strokeWidth: "2"
},
/* @__PURE__ */ import_react10.default.createElement(
"animateTransform",
{
attributeName: "transform",
type: "rotate",
from: "0 18 18",
to: "360 18 18",
dur: "0.9s",
repeatCount: "indefinite"
}
)
), /* @__PURE__ */ import_react10.default.createElement("circle", { fill: "#fff", cx: "36", cy: "18", r: "1" }, /* @__PURE__ */ import_react10.default.createElement(
"animateTransform",
{
attributeName: "transform",
type: "rotate",
from: "0 18 18",
to: "360 18 18",
dur: "0.9s",
repeatCount: "indefinite"
}
))))
);
};
// src/img/Stop.tsx
var import_react11 = __toESM(require("react"));
var Stop = ({ title }) => {
return /* @__PURE__ */ import_react11.default.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "24",
height: "24",
viewBox: "0 0 24 24"
},
title !== void 0 ? /* @__PURE__ */ import_react11.default.createElement("title", null, title) : null,
/* @__PURE__ */ import_react11.default.createElement("path", { d: "M0 0h24v24H0z", fill: "none" }),
/* @__PURE__ */ import_react11.default.createElement("path", { d: "M6 6h12v12H6z" })
);
};
// src/img/StreamStats.tsx
var import_react12 = __toESM(require("react"));
var StreamStats = ({ title }) => {
return /* @__PURE__ */ import_react12.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" }, title !== void 0 ? /* @__PURE__ */ import_react12.default.createElement("title", null, title) : null, /* @__PURE__ */ import_react12.default.createElement("path", { d: "M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z" }));
};
// src/Controls.tsx
function isHTMLMediaElement(el) {
return el.buffered !== void 0;
}
var ControlArea = import_styled_components5.default.div`
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
opacity: ${({ visible }) => visible ? 1 : 0};
transition: opacity 0.3s ease-in-out;
`;
var ControlBar = import_styled_components5.default.div`
width: 100%;
height: 32px;
background: rgb(0, 0, 0, 0.66);
display: flex;
align-items: center;
padding: 0 16px;
box-sizing: border-box;
`;
var VolumeContainer = import_styled_components5.default.div`
margin-left: 8px;
`;
var Progress = import_styled_components5.default.div`
flex-grow: 2;
padding: 0 32px;
display: flex;
align-items: center;
`;
var ProgressBarContainer = import_styled_components5.default.div`
margin: 0;
width: 100%;
height: 24px;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
`;
var ProgressBar = import_styled_components5.default.div`
background-color: rgba(255, 255, 255, 0.1);
height: 1px;
position: relative;
width: 100%;
${ProgressBarContainer}:hover > & {
height: 3px;
}
`;
var ProgressBarPlayed = import_styled_components5.default.div.attrs(
({ fraction }) => {
return {
style: { transform: `scaleX(${fraction})` }
};
}
)`
background-color: rgb(240, 180, 0);
height: 100%;
position: absolute;
top: 0;
transform: scaleX(0);
transform-origin: 0 0;
width: 100%;
`;
var ProgressBarBuffered = import_styled_components5.default.div.attrs(
({ fraction }) => {
return {
style: { transform: `scaleX(${fraction})` }
};
}
)`
background-color: rgba(255, 255, 255, 0.2);
height: 100%;
position: absolute;
top: 0;
transform: scaleX(0);
transform-origin: 0 0;
width: 100%;
`;
var ProgressTimestamp = import_styled_components5.default.div.attrs(
({ left }) => {
return {
style: { left: `${left}px` }
};
}
)`
background-color: rgb(56, 55, 51);
border-radius: 3px;
bottom: 200%;
color: #fff;
font-size: 9px;
padding: 5px;
position: absolute;
text-align: center;
`;
var ProgressIndicator = import_styled_components5.default.div`
color: rgb(240, 180, 0);
padding-left: 24px;
font-size: 10px;
white-space: nowrap;
`;
var Controls = ({
play,
videoProperties,
duration,
startTime,
src,
parameters,
onPlay,
onStop,
onRefresh,
onSeek,
onScreenshot,
onFormat,
onVapix,
labels,
showStatsOverlay,
toggleStats,
format,
volume,
setVolume
}) => {
const controlArea = (0, import_react13.useRef)(null);
const userActive = useUserActive(controlArea);
const [settings, setSettings] = (0, import_react13.useState)(false);
const toggleSettings = (0, import_react13.useCallback)(
() => setSettings((currentSettings) => !currentSettings),
[setSettings]
);
const onVolumeChange = (0, import_react13.useCallback)(
(e) => {
if (setVolume !== void 0) {
setVolume(parseFloat(e.target.value));
}
},
[setVolume]
);
const [totalDuration, setTotalDuration] = (0, import_react13.useState)(duration);
const __mediaTimeline = (0, import_react13.useRef)({
startDateTime: startTime !== void 0 ? import_luxon.DateTime.fromISO(startTime) : void 0
});
const [progress, setProgress] = (0, import_react13.useState)({
playedFraction: 0,
bufferedFraction: 0,
counter: ""
});
(0, import_react13.useEffect)(() => {
var _a;
if (videoProperties === void 0) {
return;
}
const { el, pipeline, range } = videoProperties;
if (el === null || pipeline === void 0) {
return;
}
const [start = 0, end = duration] = range != null ? range : [0, duration];
const __duration = (_a = duration != null ? duration : end) != null ? _a : Infinity;
setTotalDuration(__duration);
const updateProgress = () => {
const played = start + pipeline.currentTime;
const buffered = isHTMLMediaElement(el) && el.buffered.length > 0 ? start + el.buffered.end(el.buffered.length - 1) : played;
const total = __duration === Infinity ? buffered : __duration;
const counter = `${import_luxon.Duration.fromMillis(played * 1e3).toFormat(
"h:mm:ss"
)} / ${import_luxon.Duration.fromMillis(total * 1e3).toFormat("h:mm:ss")}`;
setProgress({
playedFraction: played / total,
bufferedFraction: buffered / total,
counter
});
};
updateProgress();
if (isHTMLMediaElement(el)) {
el.addEventListener("ended", updateProgress);
el.addEventListener("progress", updateProgress);
el.addEventListener("timeupdate", updateProgress);
return () => {
el.removeEventListener("timeupdate", updateProgress);
el.removeEventListener("progress", updateProgress);
el.removeEventListener("ended", updateProgress);
};
}
const progressInterval = setInterval(updateProgress, 1e3);
return () => {
clearInterval(progressInterval);
};
}, [videoProperties, duration, startTime, setTotalDuration]);
const seek = (0, import_react13.useCallback)(
(e) => {
if (totalDuration === void 0) {
return;
}
const { left, width } = e.currentTarget.getBoundingClientRect();
const fraction = (e.pageX - left) / width;
onSeek(fraction * totalDuration);
},
[totalDuration, onSeek]
);
const [timestamp, setTimestamp] = (0, import_react13.useState)({ left: 0, label: "" });
const __progressBarContainerRef = (0, import_react13.useRef)(null);
(0, import_react13.useEffect)(() => {
if (startTime !== void 0) {
__mediaTimeline.current.startDateTime = import_luxon.DateTime.fromISO(startTime);
}
const el = __progressBarContainerRef.current;
if (el === null || totalDuration === void 0) {
return;
}
const { left, width } = el.getBoundingClientRect();
const showTimestamp = (e) => {
const offset = e.pageX - left;
const offsetMillis = offset / width * totalDuration * 1e3;
setTimestamp({
left: offset,
label: __mediaTimeline.current.startDateTime !== void 0 ? __mediaTimeline.current.startDateTime.plus(offsetMillis).toLocaleString(import_luxon.DateTime.DATETIME_FULL_WITH_SECONDS) : import_luxon.Duration.fromMillis(offsetMillis).toFormat("h:mm:ss")
});
};
const start = () => {
el.addEventListener("pointermove", showTimestamp);
};
const stop = () => {
setTimestamp({ left: 0, label: "" });
el.removeEventListener("pointermove", showTimestamp);
};
el.addEventListener("pointerover", start);
el.addEventListener("pointerout", stop);
return () => {
el.removeEventListener("pointerout", stop);
el.removeEventListener("pointerover", start);
};
}, [startTime, totalDuration]);
return /* @__PURE__ */ import_react13.default.createElement(
ControlArea,
{
ref: controlArea,
visible: play !== true || settings || userActive
},
/* @__PURE__ */ import_react13.default.createElement(ControlBar, null, /* @__PURE__ */ import_react13.default.createElement(Button, { onClick: onPlay }, play === true ? /* @__PURE__ */ import_react13.default.createElement(Pause, { title: labels == null ? void 0 : labels.pause }) : /* @__PURE__ */ import_react13.default.createElement(Play, { title: labels == null ? void 0 : labels.play })), src !== void 0 && /* @__PURE__ */ import_react13.default.createElement(Button, { onClick: onStop }, /* @__PURE__ */ import_react13.default.createElement(Stop, { title: labels == null ? void 0 : labels.stop })), src !== void 0 && /* @__PURE__ */ import_react13.default.createElement(Button, { onClick: onRefresh }, /* @__PURE__ */ import_react13.default.createElement(Refresh, { title: labels == null ? void 0 : labels.refresh })), src !== void 0 && /* @__PURE__ */ import_react13.default.createElement(Button, { onClick: onScreenshot }, /* @__PURE__ */ import_react13.default.createElement(Screenshot, { title: labels == null ? void 0 : labels.screenshot })), volume !== void 0 ? /* @__PURE__ */ import_react13.default.createElement(VolumeContainer, { title: labels == null ? void 0 : labels.volume }, /* @__PURE__ */ import_react13.default.createElement(
"input",
{
type: "range",
min: "0",
max: "1",
step: "0.05",
onChange: onVolumeChange,
value: volume != null ? volume : 0
}
)) : null, /* @__PURE__ */ import_react13.default.createElement(Progress, null, /* @__PURE__ */ import_react13.default.createElement(ProgressBarContainer, { onClick: seek, ref: __progressBarContainerRef }, /* @__PURE__ */ import_react13.default.createElement(ProgressBar, null, /* @__PURE__ */ import_react13.default.createElement(ProgressBarPlayed, { fraction: progress.playedFraction }), /* @__PURE__ */ import_react13.default.createElement(ProgressBarBuffered, { fraction: progress.bufferedFraction }), timestamp.left !== 0 ? /* @__PURE__ */ import_react13.default.createElement(ProgressTimestamp, { left: timestamp.left }, timestamp.label) : null)), /* @__PURE__ */ import_react13.default.createElement(ProgressIndicator, null, totalDuration === Infinity ? "\u2219 LIVE" : progress.counter)), /* @__PURE__ */ import_react13.default.createElement(Button, { onClick: toggleSettings }, /* @__PURE__ */ import_react13.default.createElement(CogWheel, { title: labels == null ? void 0 : labels.settings }))),
settings && /* @__PURE__ */ import_react13.default.createElement(
Settings,
{
parameters,
format,
onFormat,
onVapix,
showStatsOverlay,
toggleStats
}
)
);
};
// src/PlaybackArea.tsx
var import_react20 = __toESM(require("react"));
var import_debug5 = __toESM(require("debug"));
// src/HttpMp4Video.tsx
var import_react16 = __toESM(require("react"));
var import_debug = __toESM(require("debug"));
var import_media_stream_library = require("media-stream-library");
var import_styled_components6 = __toESM(require("styled-components"));
// src/constants.ts
var FORMAT_SUPPORTS_AUDIO = {
RTP_H264: true,
RTP_JPEG: false,
MP4_H264: true,
JPEG: false,
MJPEG: false
};
// src/hooks/useEventState.ts
var import_react14 = require("react");
var useEventState = (ref, eventName) => {
const [eventState, setEventState] = (0, import_react14.useState)(false);
const setEventStateTrue = (0, import_react14.useCallback)(() => setEventState(true), []);
const setEventStateFalse = (0, import_react14.useCallback)(() => setEventState(false), []);
(0, import_react14.useEffect)(() => {
const el = ref.current;
if (!eventState && el !== null) {
el.addEventListener(eventName, setEventStateTrue);
return () => {
el.removeEventListener(eventName, setEventStateTrue);
};
}
}, [eventState, eventName, ref, setEventStateTrue]);
return [eventState, setEventStateFalse];
};
// src/hooks/useVideoDebug.ts
var import_react15 = require("react");
var useVideoDebug = (videoEl, debugLog6) => {
(0, import_react15.useEffect)(() => {
if (videoEl === null) {
return;
}
const onUpdate = () => {
try {
const currentTime = videoEl.currentTime;
const bufferedEnd = videoEl.buffered.end(videoEl.buffered.length - 1);
debugLog6("%o", {
delay: bufferedEnd - currentTime,
currentTime,
bufferedEnd
});
} catch (err) {
debugLog6("%o", err);
}
};
videoEl.addEventListener("timeupdate", onUpdate);
videoEl.addEventListener("progress", onUpdate);
return () => {
videoEl.removeEventListener("timeupdate", onUpdate);
videoEl.removeEventListener("progress", onUpdate);
};
}, [debugLog6, videoEl]);
};
// src/types.ts
var Format = /* @__PURE__ */ ((Format2) => {
Format2["RTP_H264"] = "RTP_H264";
Format2["RTP_JPEG"] = "RTP_JPEG";
Format2["JPEG"] = "JPEG";
Format2["MJPEG"] = "MJPEG";
Format2["MP4_H264"] = "MP4_H264";
return Format2;
})(Format || {});
// src/HttpMp4Video.tsx
var debugLog = (0, import_debug.default)("msp:http-mp4-video");
var VideoNative = import_styled_components6.default.video`
max-height: 100%;
object-fit: contain;
width: 100%;
`;
var HttpMp4Video = ({
forwardedRef,
play = false,
src,
autoPlay = true,
muted = true,
onPlaying,
onEnded,
metadataHandler
}) => {
let videoRef = (0, import_react16.useRef)(null);
if (typeof forwardedRef === "function") {
forwardedRef(videoRef.current);
} else if (forwardedRef) {
videoRef = forwardedRef;
}
const [canplay, unsetCanplay] = useEventState(videoRef, "canplay");
const [playing, unsetPlaying] = useEventState(videoRef, "playing");
const [pipeline, setPipeline] = (0, import_react16.useState)(
null
);
const [fetching, setFetching] = (0, import_react16.useState)(false);
const __onPlayingRef = (0, import_react16.useRef)(onPlaying);
__onPlayingRef.current = onPlaying;
const __onEndedRef = (0, import_react16.useRef)(onEnded);
__onEndedRef.current = onEnded;
const __sensorTmRef = (0, import_react16.useRef)();
useVideoDebug(videoRef.current, debugLog);
(0, import_react16.useEffect)(() => {
const videoEl = videoRef.current;
if (videoEl === null) {
return;
}
if (play && canplay === true && playing === false) {
debugLog("play");
videoEl.play().catch((err) => {
console.error("VideoElement error: ", err.message);
});
const { videoHeight, videoWidth } = videoEl;
debugLog("%o", {
videoHeight,
videoWidth
});
} else if (!play && playing === true) {
debugLog("pause");
videoEl.pause();
unsetPlaying();
} else if (play && playing === true) {
if (__onPlayingRef.current !== void 0) {
__onPlayingRef.current({
el: videoEl,
width: videoEl.videoWidth,
height: videoEl.videoHeight,
sensorTm: __sensorTmRef.current,
formatSupportsAudio: FORMAT_SUPPORTS_AUDIO["MP4_H264" /* MP4_H264 */]
// TODO: no volume, need to expose tracks?
// TODO: no pipeline, can we even get stats?
});
}
}
}, [play, canplay, playing, unsetPlaying, pipeline]);
const __metadataHandlerRef = (0, import_react16.useRef)(metadataHandler);
__metadataHandlerRef.current = metadataHandler;
(0, import_react16.useEffect)(() => {
const videoEl = videoRef.current;
if (src !== void 0 && src.length > 0 && videoEl !== null) {
const endedCallback = () => {
var _a;
(_a = __onEndedRef.current) == null ? void 0 : _a.call(__onEndedRef);
};
debugLog("create pipeline", src);
const newPipeline = new import_media_stream_library.pipelines.HttpMsePipeline({
http: { uri: src },
mediaElement: videoEl
});
setPipeline(newPipeline);
newPipeline.onServerClose = endedCallback;
return () => {
debugLog("close pipeline and clear video");
newPipeline.close();
videoEl.src = "";
setPipeline(null);
setFetching(false);
unsetCanplay();
unsetPlaying();
};
}
}, [src, unsetCanplay, unsetPlaying]);
(0, import_react16.useEffect)(() => {
if (play && pipeline && !fetching) {
pipeline.onHeaders = (headers) => {
var _a;
__sensorTmRef.current = parseTransformHeader(
(_a = headers.get("video-sensor-transform")) != null ? _a : headers.get("video-metadata-transform")
);
};
pipeline.http.play();
debugLog("initiated data fetching");
setFetching(true);
}
}, [play, pipeline, fetching]);
return /* @__PURE__ */ import_react16.default.createElement(VideoNative, { autoPlay, muted, ref: videoRef });
};
var parseTransformHeader = (value) => {
if (value === void 0 || value === null) {
return void 0;
}
return value.split(";").map((row) => row.split(",").map(Number));
};
// src/StillImage.tsx
var import_react17 = __toESM(require("react"));
var import_debug2 = __toESM(require("debug"));
var import_styled_components7 = __toESM(require("styled-components"));
var debugLog2 = (0, import_debug2.default)("msp:still-image");
var ImageNative = import_styled_components7.default.img`
max-height: 100%;
object-fit: contain;
width: 100%;
`;
var cachebust = 0;
var StillImage = ({
forwardedRef,
play = false,
onPlaying,
src
}) => {
let imgRef = (0, import_react17.useRef)(null);
if (typeof forwardedRef === "function") {
forwardedRef(imgRef.current);
} else if (forwardedRef) {
imgRef = forwardedRef;
}
const [loaded, unsetLoaded] = useEventState(imgRef, "load");
(0, import_react17.useEffect)(() => {
const imgEl = imgRef.current;
if (imgEl === null) {
return;
}
if (play && src !== void 0) {
imgEl.src = `${src}&cachebust=${cachebust++}`;
return () => {
imgEl.src = "";
unsetLoaded();
};
}
}, [play, src, unsetLoaded]);
const __onPlayingRef = (0, import_react17.useRef)(onPlaying);
__onPlayingRef.current = onPlaying;
(0, import_react17.useEffect)(() => {
const el = imgRef.current;
if (loaded && el !== null && __onPlayingRef.current !== void 0) {
__onPlayingRef.current({
el,
width: el.naturalWidth,
height: el.naturalHeight,
formatSupportsAudio: FORMAT_SUPPORTS_AUDIO["JPEG" /* JPEG */]
});
}
}, [loaded]);
debugLog2("render image", loaded);
return /* @__PURE__ */ import_react17.default.createElement(ImageNative, { ref: imgRef });
};
// src/WsRtspCanvas.tsx
var import_react18 = __toESM(require("react"));
var import_debug3 = __toESM(require("debug"));
var import_media_stream_library2 = require("media-stream-library");
var import_styled_components8 = __toESM(require("styled-components"));
var debugLog3 = (0, import_debug3.default)("msp:ws-rtsp-video");
var CanvasNative = import_styled_components8.default.canvas`
max-height: 100%;
object-fit: contain;
width: 100%;
`;
var WsRtspCanvas = ({
forwardedRef,
play = true,
ws = "",
rtsp = "",
onPlaying,
onEnded,
onSdp,
onRtcp,
offset = 0,
autoRetry = false
}) => {
let canvasRef = (0, import_react18.useRef)(null);
if (typeof forwardedRef === "function") {
forwardedRef(canvasRef.current);
} else if (forwardedRef) {
canvasRef = forwardedRef;
}
const [pipeline, setPipeline] = (0, import_react18.useState)(null);
const [fetching, setFetching] = (0, import_react18.useState)(false);
const __offsetRef = (0, import_react18.useRef)(offset);
const __rangeRef = (0, import_react18.useRef)([offset, void 0]);
const timeout = (0, import_react18.useRef)(void 0);
(0, import_react18.useEffect)(() => {
if (pipeline === null) {
return;
}
timeout.current = window.setInterval(() => {
const { currentTime } = pipeline;
debugLog3("%o", { currentTime });
}, 1e3);
return () => window.clearTimeout(timeout.current);
}, [pipeline]);
(0, import_react18.useEffect)(() => {
__offsetRef.current = offset;
const canvas = canvasRef.current;
if (ws && rtsp && canvas) {
debugLog3("create pipeline");
const newPipeline = new import_media_stream_library2.pipelines.Html5CanvasPipeline({
ws: { uri: ws },
rtsp: { uri: rtsp },
mediaElement: canvas
});
if (autoRetry) {
import_media_stream_library2.utils.addRTSPRetry(newPipeline.rtsp);
}
setPipeline(newPipeline);
return () => {
debugLog3("destroy pipeline");
newPipeline.pause();
newPipeline.close();
setPipeline(null);
setFetching(false);
debugLog3("canvas cleared");
};
}
}, [ws, rtsp, offset, autoRetry]);
const __onPlayingRef = (0, import_react18.useRef)(onPlaying);
__onPlayingRef.current = onPlaying;
const __onEndedRef = (0, import_react18.useRef)(onEnded);
__onEndedRef.current = onEnded;
const __onSdpRef = (0, import_react18.useRef)(onSdp);
__onSdpRef.current = onSdp;
const __onRtcpRef = (0, import_react18.useRef)(onRtcp);
__onRtcpRef.current = onRtcp;
const __sensorTmRef = (0, import_react18.useRef)();
(0, import_react18.useEffect)(() => {
if (play && pipeline && !fetching) {
pipeline.ready.then(() => {
debugLog3("fetch");
pipeline.onSdp = (sdp) => {
var _a;
const videoMedia = sdp.media.find((m) => {
return m.type === "video";
});
if (videoMedia !== void 0) {
__sensorTmRef.current = (_a = videoMedia["x-sensor-transform"]) != null ? _a : videoMedia["transform"];
}
if (__onSdpRef.current !== void 0) {
__onSdpRef.current(sdp);
}
};
pipeline.rtsp.onRtcp = (rtcp) => {
var _a, _b;
(_a = __onRtcpRef.current) == null ? void 0 : _a.call(__onRtcpRef, rtcp);
if ((0, import_media_stream_library2.isRtcpBye)(rtcp)) {
(_b = __onEndedRef.current) == null ? void 0 : _b.call(__onEndedRef);
}
};
pipeline.rtsp.onPlay = (range) => {
if (range !== void 0) {
__rangeRef.current = [
parseFloat(range[0]) || 0,
parseFloat(range[1]) || void 0
];
}
};
pipeline.rtsp.play(__offsetRef.current);
setFetching(true);
}).catch(console.error);
} else if (play && pipeline !== null) {
debugLog3("play");
pipeline.play();
pipeline.onCanplay = () => {
if (canvasRef.current !== null && __onPlayingRef.current !== void 0) {
__onPlayingRef.current({
el: canvasRef.current,
width: canvasRef.current.width,
height: canvasRef.current.height,
formatSupportsAudio: FORMAT_SUPPORTS_AUDIO["RTP_JPEG" /* RTP_JPEG */],
range: __rangeRef.current,
sensorTm: __sensorTmRef.current
});
}
};
} else if (!play && pipeline) {
debugLog3("pause");
pipeline.pause();
}
}, [play, pipeline, fetching]);
return /* @__PURE__ */ import_react18.default.createElement(CanvasNative, { ref: canvasRef });
};
// src/WsRtspVideo.tsx
var import_react19 = __toESM(require("react"));
var import_debug4 = __toESM(require("debug"));
var import_media_stream_library4 = require("media-stream-library");
var import_styled_components9 = __toESM(require("styled-components"));
// src/metadata.ts
var import_media_stream_library3 = require("media-stream-library");
var attachMetadataHandler = (pipeline, { parser, cb }) => {
const scheduler = new import_media_stream_library3.utils.Scheduler(pipeline, cb, 30);
const xmlParser = new DOMParser();
const xmlMessageHandler = (msg) => {
const xmlDocument = xmlParser.parseFromString(
msg.data.toString(),
"text/xml"
);
const newMsg = parser(__spreadProps(__spreadValues({}, msg), { xmlDocument }));
if (msg.ntpTimestamp !== void 0) {
scheduler.run(newMsg);
}
};
const onvifDepay = new import_media_stream_library3.components.ONVIFDepay();
const onvifHandlerPipe = import_media_stream_library3.components.Tube.fromHandlers((msg) => {
if (msg.type === import_media_stream_library3.MessageType.XML) {
xmlMessageHandler(msg);
}
}, void 0);
pipeline.insertAfter(pipeline.rtsp, onvifDepay);
pipeline.insertAfter(onvifDepay, onvifHandlerPipe);
pipeline.onSync = (ntpPresentationTime) => scheduler.init(ntpPresentationTime);
return scheduler;
};
// src/WsRtspVideo.tsx
var debugLog4 = (0, import_debug4.default)("msp:ws-rtsp-video");
var VideoNative2 = import_styled_components9.default.video`
max-height: 100%;
object-fit: contain;
width: 100%;
`;
var WsRtspVideo = ({
forwardedRef,
play = false,
ws,
rtsp,
autoPlay = true,
muted = true,
onPlaying,
onEnded,
onSdp,
onRtcp,
metadataHandler,
offset = 0,
autoRetry = false
}) => {
let videoRef = (0, import_react19.useRef)(null);
if (typeof forwardedRef === "function") {
forwardedRef(videoRef.current);
} else if (forwardedRef) {
videoRef = forwardedRef;
}
const [canplay, unsetCanplay] = useEventState(videoRef, "canplay");
const [playing, unsetPlaying] = useEventState(videoRef, "playing");
const [pipeline, setPipeline] = (0, import_react19.useState)(
null
);
const [fetching, setFetching] = (0, import_react19.useState)(false);
const __offsetRef = (0, import_react19.useRef)(offset);
const __rangeRef = (0, import_react19.useRef)([offset, void 0]);
const __onPlayingRef = (0, import_react19.useRef)(onPlaying);
__onPlayingRef.current = onPlaying;
const __onEndedRef = (0, import_react19.useRef)(onEnded);
__onEndedRef.current = onEnded;
const __sensorTmRef = (0, import_react19.useRef)();
useVideoDebug(videoRef.current, debugLog4);
(0, import_react19.useEffect)(() => {
var _a;
const videoEl = videoRef.current;
if (videoEl === null) {
return;
}
if (play && canplay === true && playing === false) {
debugLog4("play");
videoEl.play().catch((err) => {
console.error("VideoElement error: ", err.message);
});
const { videoHeight, videoWidth } = videoEl;
debugLog4("%o", {
videoHeight,
videoWidth
});
} else if (!play && playing === true) {
debugLog4("pause");
videoEl.pause();
unsetPlaying();
} else if (play && playing === true) {
if (__onPlayingRef.current !== void 0) {
__onPlayingRef.current({
el: videoEl,
pipeline: pipeline != null ? pipeline : void 0,
width: videoEl.videoWidth,
height: videoEl.videoHeight,
formatSupportsAudio: FORMAT_SUPPORTS_AUDIO["RTP_H264" /* RTP_H264 */],
volume: ((_a = pipeline == null ? void 0 : pipeline.tracks) == null ? void 0 : _a.find((track) => track.type === "audio")) ? videoEl.volume : void 0,
range: __rangeRef.current,
sensorTm: __sensorTmRef.current
});
}
}
}, [play, canplay, playing, unsetPlaying, pipeline]);
const __metadataHandlerRef = (0, import_react19.useRef)(metadataHandler);
__metadataHandlerRef.current = metadataHandler;
(0, import_react19.useEffect)(() => {
const videoEl = videoRef.current;
__offsetRef.current = offset;
if (ws !== void 0 && ws.length > 0 && rtsp !== void 0 && rtsp.length > 0 && videoEl !== null) {
debugLog4("create pipeline", ws, rtsp);
const newPipeline = new import_media_stream_library4.pipelines.Html5VideoPipeline({
ws: { uri: ws },
rtsp: { uri: rtsp },
mediaElement: videoEl
});
if (autoRetry) {
import_media_stream_library4.utils.addRTSPRetry(newPipeline.rtsp);
}
setPipeline(newPipeline);
let scheduler;
if (__metadataHandlerRef.current !== void 0) {
scheduler = attachMetadataHandler(
newPipeline,
__metadataHandlerRef.current
);
}
return () => {
debugLog4("close pipeline and clear video");
newPipeline.close();
videoEl.src = "";
scheduler == null ? void 0 : scheduler.reset();
setPipeline(null);
setFetching(false);
unsetCanplay();
unsetPlaying();
};
}
}, [ws, rtsp, offset, unsetCanplay, unsetPlaying, autoRetry]);
const __onSdpRef = (0, import_react19.useRef)(onSdp);
__onSdpRef.current = onSdp;
const __onRtcpRef = (0, import_react19.useRef)(onRtcp);
__onRtcpRef.current = onRtcp;
(0, import_react19.useEffect)(() => {
if (play && pipeline && !fetching) {
pipeline.ready.then(() => {
pipeline.onSdp = (sdp) => {
var _a;
const videoMedia = sdp.media.find((m) => {
return m.type === "video";
});
if (videoMedia !== void 0) {
__sensorTmRef.current = (_a = videoMedia["x-sensor-transform"]) != null ? _a : videoMedia["transform"];
}
if (__onSdpRef.current !== void 0) {
__onSdpRef.current(sdp);
}
};
pipeline.rtsp.onRtcp = (rtcp) => {
var _a, _b;
(_a = __onRtcpRef.current) == null ? void 0 : _a.call(__onRtcpRef, rtcp);
if ((0, import_media_stream_library4.isRtcpBye)(rtcp)) {
(_b = __onEndedRef.current) == null ? void 0 : _b.call(__onEndedRef);
}
};
pipeline.rtsp.onPlay = (range) => {
if (range !== void 0) {
__rangeRef.current = [
parseFloat(range[0]) || 0,
parseFloat(range[1]) || void 0
];
}
};
pipeline.rtsp.play(__offsetRef.current);
}).catch((err) => {
console.error(err);
});
debugLog4("initiated data fetching");
setFetching(true);
}
}, [play, pipeline, fetching]);
return /* @__PURE__ */ import_react19.default.createElement(VideoNative2, { autoPlay, muted, ref: videoRef });
};
// src/PlaybackArea.tsx
var debugLog5 = (0, import_debug5.default)("msp:api");
var AxisApi = /* @__PURE__ */ ((AxisApi2) => {
AxisApi2["AXIS_IMAGE_CGI"] = "AXIS_IMAGE_CGI";
AxisApi2["AXIS_MEDIA_AMP"] = "AXIS_MEDIA_AMP";
AxisApi2["AXIS_MEDIA_CGI"] = "AXIS_MEDIA_CGI";
AxisApi2["AXIS_MJPEG_CGI"] = "AXIS_MJPEG_CGI";
return AxisApi2;
})(AxisApi || {});
var Protocol = /* @__PURE__ */ ((Protocol2) => {
Protocol2["HTTP"] = "http:";
Protocol2["HTTPS"] = "https:";
Protocol2["WS"] = "ws:";
Protocol2["WSS"] = "wss:";
return Protocol2;
})(Protocol || {});
var FORMAT_API = {
RTP_H264: "AXIS_MEDIA_AMP" /* AXIS_MEDIA_AMP */,
RTP_JPEG: "AXIS_MEDIA_AMP" /* AXIS_MEDIA_AMP */,
MJPEG: "AXIS_MJPEG_CGI" /* AXIS_MJPEG_CGI */,
MP4_H264: "AXIS_MEDI