UNPKG

media-stream-player

Version:

Player built on top of media-stream-library

191 lines (190 loc) 6.36 kB
import React, { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import { useInterval } from 'react-hooks-shareable'; import { Format } from './PlaybackArea'; import { StreamStats } from './img'; const isHtml5VideoPipeline = (pipeline) => { var _a; return ((_a = pipeline) === null || _a === void 0 ? void 0 : _a.tracks) !== undefined; }; const StatsWrapper = styled.div ` position: absolute; top: 24px; left: 24px; width: 360px; min-width: 240px; max-width: 80%; max-height: 80%; border-radius: 4px; background: #292929 0% 0% no-repeat padding-box; opacity: 0.88; `; const StatsHeader = styled.div ` padding: 8px 24px; border-bottom: 1px solid #525252; `; const StatsIcon = styled.span ` width: 24px; height: 24px; float: left; cursor: ${({ clickable }) => (clickable ? 'pointer' : 'default')}; & > svg { fill: #e0e0e0; } `; const StatsTitle = styled.span ` display: inline-block; margin-left: 8px; vertical-align: sub; text-align: left; font-size: 16px; font-family: 'Open Sans', Sans-Serif; line-height: 22px; color: #f5f5f5; `; const StatsHide = styled.span ` float: right; text-align: right; `; const HideLink = styled.a ` vertical-align: sub; text-decoration: none; font-size: 16px; font-family: 'Open Sans', Sans-Serif; line-height: 22px; color: #b8b8b8; `; const Data = styled.div ` display: grid; grid-template-columns: repeat(3, 1fr); column-gap: 24px; row-gap: 16px; width: 100%; padding: 16px 24px 24px; `; const StatItem = styled.div ` text-align: left; font-family: 'Open Sans', Sans-Serif; `; const StatName = styled.div ` font-size: 12px; line-height: 17px; color: #b8b8b8; `; const StatValue = styled.div ` font-size: 13px; line-height: 18px; color: #e0e0e0; `; const StatsShow = styled.div ` position: absolute; top: 24px; left: 24px; width: 32px; height: 32px; display: flex; justify-content: center; align-items: center; border-radius: 4px; background: #292929 0% 0% no-repeat padding-box; opacity: 0.88; `; const StatsData = ({ format, videoProperties, refresh, volume, }) => { const [stats, setStats] = useState([]); // Updates stat values const updateValues = useCallback(() => { var _a; let streamType = 'Unknown'; if (format === Format.JPEG) { streamType = 'Still image'; } else if (format === Format.RTP_H264) { streamType = 'RTSP (WebSocket)'; } else if (format === Format.RTP_JPEG) { streamType = 'MJPEG'; } else if (format === Format.MP4_H264) { streamType = 'MP4 (HTTP)'; } const { width, height, pipeline } = videoProperties; let statsData = [ { name: 'Stream type', value: streamType, }, { name: 'Resolution', value: `${width}x${height}`, }, { name: 'Refreshed', value: refresh, unit: refresh > 1 ? 'times' : 'time', }, ]; if (isHtml5VideoPipeline(pipeline)) { const tracks = (_a = pipeline.tracks) === null || _a === void 0 ? void 0 : _a.map((track, index) => Object.assign({ index }, track)); const videoTrack = tracks === null || tracks === void 0 ? void 0 : tracks.find((track) => track.type === 'video'); if (videoTrack !== undefined) { const { coding, profile, level } = videoTrack === null || videoTrack === void 0 ? void 0 : videoTrack.codec; const framerate = Number(pipeline.framerate[videoTrack.index].toFixed(2)); const bitrate = Math.round(pipeline.bitrate[videoTrack.index] / 1000); statsData = statsData.concat([ { name: 'Encoding', value: `${coding} ${profile} (${level})`, }, { name: 'Frame rate', value: framerate, unit: 'fps', }, { name: 'Bitrate', value: bitrate, unit: 'kbit/s', }, ]); } } if (volume !== undefined) { statsData.push({ name: 'Volume', value: Math.floor(volume * 100), unit: '%', }); } setStats(statsData); }, [format, refresh, videoProperties, volume]); useEffect(() => { updateValues(); }, [updateValues]); useInterval(updateValues, 1000); return (React.createElement(Data, null, stats.length > 0 ? stats.map((stat) => { return (React.createElement(StatItem, { key: stat.name }, React.createElement(StatName, null, stat.name), React.createElement(StatValue, null, `${stat.value} ${stat.unit !== undefined ? stat.unit : ''}`))); }) : null)); }; export const Stats = ({ format, videoProperties, refresh, volume, }) => { const [showStats, setShowStats] = useState(true); // Handles show/hide stats const onToggleStats = useCallback((e) => { e.preventDefault(); setShowStats((prevState) => !prevState); }, [setShowStats]); return (React.createElement(React.Fragment, null, showStats ? (React.createElement(StatsWrapper, null, React.createElement(StatsHeader, null, React.createElement(StatsIcon, { clickable: false }, React.createElement(StreamStats, null)), React.createElement(StatsTitle, null, "Client stream data"), React.createElement(StatsHide, null, React.createElement(HideLink, { href: "", onClick: onToggleStats }, "Hide"))), React.createElement(StatsData, { format: format, videoProperties: videoProperties, refresh: refresh, volume: volume }))) : (React.createElement(StatsShow, null, React.createElement(StatsIcon, { onClick: onToggleStats, clickable: true }, React.createElement(StreamStats, { title: "Show client stream data" })))))); }; //# sourceMappingURL=Stats.js.map