import React from 'react'; import PropTypes from 'prop-types'; import ReactTooltip from 'react-tooltip'; import classnames from 'classnames'; import Spinner from 'react-spinner'; import clipboardCopy from 'clipboard-copy'; import hark from 'hark'; import * as faceapi from 'face-api.js'; import Logger from '../Logger'; import * as appPropTypes from './appPropTypes'; import EditableInput from './EditableInput'; const logger = new Logger('PeerView'); const tinyFaceDetectorOptions = new faceapi.TinyFaceDetectorOptions( { inputSize : 160, scoreThreshold : 0.5 }); export default class PeerView extends React.Component { constructor(props) { super(props); this.state = { audioVolume : 0, // Integer from 0 to 10., showInfo : window.SHOW_INFO || false, videoResolutionWidth : null, videoResolutionHeight : null, videoCanPlay : false, videoElemPaused : false, maxSpatialLayer : null }; // Latest received video track. // @type {MediaStreamTrack} this._audioTrack = null; // Latest received video track. // @type {MediaStreamTrack} this._videoTrack = null; // Hark instance. // @type {Object} this._hark = null; // Periodic timer for reading video resolution. this._videoResolutionPeriodicTimer = null; // requestAnimationFrame for face detection. this._faceDetectionRequestAnimationFrame = null; } render() { const { isMe, peer, audioProducerId, videoProducerId, audioConsumerId, videoConsumerId, videoRtpParameters, consumerSpatialLayers, consumerTemporalLayers, consumerCurrentSpatialLayer, consumerCurrentTemporalLayer, consumerPreferredSpatialLayer, consumerPreferredTemporalLayer, consumerPriority, audioMuted, videoVisible, videoMultiLayer, audioCodec, videoCodec, audioScore, videoScore, onChangeDisplayName, onChangeMaxSendingSpatialLayer, onChangeVideoPreferredLayers, onChangeVideoPriority, onRequestKeyFrame, onStatsClick } = this.props; const { audioVolume, showInfo, videoResolutionWidth, videoResolutionHeight, videoCanPlay, videoElemPaused, maxSpatialLayer } = this.state; return (
{'id: '} clipboardCopy(`"${audioProducerId}"`)} > {audioProducerId}
{'id: '} clipboardCopy(`"${audioConsumerId}"`)} > {audioConsumerId}
codec: {audioCodec}
{'id: '} clipboardCopy(`"${videoProducerId}"`)} > {videoProducerId}
{'id: '} clipboardCopy(`"${videoConsumerId}"`)} > {videoConsumerId}
codec: {videoCodec}
resolution: {videoResolutionWidth}x{videoResolutionHeight}
max spatial layer: {maxSpatialLayer > -1 ? maxSpatialLayer : 'none'} {' '} -1 })} onClick={(event) => { event.stopPropagation(); const newMaxSpatialLayer = maxSpatialLayer -1; onChangeMaxSendingSpatialLayer(newMaxSpatialLayer); this.setState({ maxSpatialLayer: newMaxSpatialLayer }); }} > {'[ down ]'} {' '} { event.stopPropagation(); const newMaxSpatialLayer = maxSpatialLayer + 1; onChangeMaxSendingSpatialLayer(newMaxSpatialLayer); this.setState({ maxSpatialLayer: newMaxSpatialLayer }); }} > {'[ up ]'}
{`current spatial-temporal layers: ${consumerCurrentSpatialLayer} ${consumerCurrentTemporalLayer}`}
{`preferred spatial-temporal layers: ${consumerPreferredSpatialLayer} ${consumerPreferredTemporalLayer}`} {' '} { event.stopPropagation(); let newPreferredSpatialLayer = consumerPreferredSpatialLayer; let newPreferredTemporalLayer; if (consumerPreferredTemporalLayer > 0) { newPreferredTemporalLayer = consumerPreferredTemporalLayer - 1; } else { if (consumerPreferredSpatialLayer > 0) newPreferredSpatialLayer = consumerPreferredSpatialLayer - 1; else newPreferredSpatialLayer = consumerSpatialLayers - 1; newPreferredTemporalLayer = consumerTemporalLayers - 1; } onChangeVideoPreferredLayers( newPreferredSpatialLayer, newPreferredTemporalLayer); }} > {'[ down ]'} {' '} { event.stopPropagation(); let newPreferredSpatialLayer = consumerPreferredSpatialLayer; let newPreferredTemporalLayer; if (consumerPreferredTemporalLayer < consumerTemporalLayers - 1) { newPreferredTemporalLayer = consumerPreferredTemporalLayer + 1; } else { if (consumerPreferredSpatialLayer < consumerSpatialLayers - 1) newPreferredSpatialLayer = consumerPreferredSpatialLayer + 1; else newPreferredSpatialLayer = 0; newPreferredTemporalLayer = 0; } onChangeVideoPreferredLayers( newPreferredSpatialLayer, newPreferredTemporalLayer); }} > {'[ up ]'}
{`priority: ${consumerPriority}`} {' '} 1 })} onClick={(event) => { event.stopPropagation(); onChangeVideoPriority(consumerPriority - 1); }} > {'[ down ]'} {' '} { event.stopPropagation(); onChangeVideoPriority(consumerPriority + 1); }} > {'[ up ]'}
{ event.stopPropagation(); if (!onRequestKeyFrame) return; onRequestKeyFrame(); }} > {'[ request keyframe ]'}
streams:
{ scores .sort((a, b) => { if (a.rid) return (a.rid > b.rid ? 1 : -1); else return (a.ssrc > b.ssrc ? 1 : -1); }) .map(({ ssrc, rid, score }, idx) => ( // eslint-disable-line no-shadow
{`score:${score.score}, producerScore:${score.producerScore}, producerScores:[${score.producerScores}]`}
); } } PeerView.propTypes = { isMe : PropTypes.bool, peer : PropTypes.oneOfType( [ appPropTypes.Me, appPropTypes.Peer ]).isRequired, audioProducerId : PropTypes.string, videoProducerId : PropTypes.string, audioConsumerId : PropTypes.string, videoConsumerId : PropTypes.string, audioRtpParameters : PropTypes.object, videoRtpParameters : PropTypes.object, consumerSpatialLayers : PropTypes.number, consumerTemporalLayers : PropTypes.number, consumerCurrentSpatialLayer : PropTypes.number, consumerCurrentTemporalLayer : PropTypes.number, consumerPreferredSpatialLayer : PropTypes.number, consumerPreferredTemporalLayer : PropTypes.number, consumerPriority : PropTypes.number, audioTrack : PropTypes.any, videoTrack : PropTypes.any, audioMuted : PropTypes.bool, videoVisible : PropTypes.bool.isRequired, videoMultiLayer : PropTypes.bool, audioCodec : PropTypes.string, videoCodec : PropTypes.string, audioScore : PropTypes.any, videoScore : PropTypes.any, faceDetection : PropTypes.bool.isRequired, onChangeDisplayName : PropTypes.func, onChangeMaxSendingSpatialLayer : PropTypes.func, onChangeVideoPreferredLayers : PropTypes.func, onChangeVideoPriority : PropTypes.func, onRequestKeyFrame : PropTypes.func, onStatsClick : PropTypes.func.isRequired };