You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Video.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import PropTypes from 'prop-types';
  2. import React, { Component } from 'react';
  3. /**
  4. * Component that renders a video element for a passed in video track.
  5. *
  6. * @extends Component
  7. */
  8. class Video extends Component {
  9. /**
  10. * Default values for {@code Video} component's properties.
  11. *
  12. * @static
  13. */
  14. static defaultProps = {
  15. className: '',
  16. id: ''
  17. };
  18. /**
  19. * {@code Video} component's property types.
  20. *
  21. * @static
  22. */
  23. static propTypes = {
  24. /**
  25. * CSS classes to add to the video element.
  26. */
  27. className: PropTypes.string,
  28. /**
  29. * The value of the id attribute of the video. Used by the torture tests
  30. * to locate video elements.
  31. */
  32. id: PropTypes.string,
  33. /**
  34. * Optional callback to invoke once the video starts playing.
  35. */
  36. onVideoPlaying: PropTypes.func,
  37. /**
  38. * The JitsiLocalTrack to display.
  39. */
  40. videoTrack: PropTypes.object
  41. };
  42. /**
  43. * Initializes a new {@code Video} instance.
  44. *
  45. * @param {Object} props - The read-only properties with which the new
  46. * instance is to be initialized.
  47. */
  48. constructor(props) {
  49. super(props);
  50. /**
  51. * The internal reference to the DOM/HTML element intended for
  52. * displaying a video.
  53. *
  54. * @private
  55. * @type {HTMLVideoElement}
  56. */
  57. this._videoElement = null;
  58. // Bind event handlers so they are only bound once for every instance.
  59. this._onVideoPlaying = this._onVideoPlaying.bind(this);
  60. this._setVideoElement = this._setVideoElement.bind(this);
  61. }
  62. /**
  63. * Invokes the library for rendering the video on initial display. Sets the
  64. * volume level to zero to ensure no sound plays.
  65. *
  66. * @inheritdoc
  67. * @returns {void}
  68. */
  69. componentDidMount() {
  70. this._videoElement.volume = 0;
  71. this._videoElement.onplaying = this._onVideoPlaying;
  72. this._attachTrack(this.props.videoTrack);
  73. }
  74. /**
  75. * Remove any existing associations between the current video track and the
  76. * component's video element.
  77. *
  78. * @inheritdoc
  79. * @returns {void}
  80. */
  81. componentWillUnmount() {
  82. this._detachTrack(this.props.videoTrack);
  83. }
  84. /**
  85. * Updates the video display only if a new track is added. This component's
  86. * updating is blackboxed from React to prevent re-rendering of video
  87. * element, as the lib uses track.attach(videoElement) instead.
  88. *
  89. * @inheritdoc
  90. * @returns {boolean} - False is always returned to blackbox this component.
  91. * from React.
  92. */
  93. shouldComponentUpdate(nextProps) {
  94. const currentJitsiTrack = this.props.videoTrack
  95. && this.props.videoTrack.jitsiTrack;
  96. const nextJitsiTrack = nextProps.videoTrack
  97. && nextProps.videoTrack.jitsiTrack;
  98. if (currentJitsiTrack !== nextJitsiTrack) {
  99. this._detachTrack(this.props.videoTrack);
  100. this._attachTrack(nextProps.videoTrack);
  101. }
  102. return false;
  103. }
  104. /**
  105. * Renders the video element.
  106. *
  107. * @override
  108. * @returns {ReactElement}
  109. */
  110. render() {
  111. return (
  112. <video
  113. autoPlay = { true }
  114. className = { this.props.className }
  115. id = { this.props.id }
  116. ref = { this._setVideoElement } />
  117. );
  118. }
  119. /**
  120. * Calls into the passed in track to associate the track with the
  121. * component's video element and render video.
  122. *
  123. * @param {Object} videoTrack - The redux representation of the
  124. * {@code JitsiLocalTrack}.
  125. * @private
  126. * @returns {void}
  127. */
  128. _attachTrack(videoTrack) {
  129. if (!videoTrack || !videoTrack.jitsiTrack) {
  130. return;
  131. }
  132. videoTrack.jitsiTrack.attach(this._videoElement);
  133. }
  134. /**
  135. * Removes the association to the component's video element from the passed
  136. * in redux representation of jitsi video track to stop the track from
  137. * rendering.
  138. *
  139. * @param {Object} videoTrack - The redux representation of the
  140. * {@code JitsiLocalTrack}.
  141. * @private
  142. * @returns {void}
  143. */
  144. _detachTrack(videoTrack) {
  145. if (this._videoElement && videoTrack && videoTrack.jitsiTrack) {
  146. videoTrack.jitsiTrack.detach(this._videoElement);
  147. }
  148. }
  149. /**
  150. * Invokes the onvideoplaying callback if defined.
  151. *
  152. * @private
  153. * @returns {void}
  154. */
  155. _onVideoPlaying() {
  156. if (this.props.onVideoPlaying) {
  157. this.props.onVideoPlaying();
  158. }
  159. }
  160. /**
  161. * Sets an instance variable for the component's video element so it can be
  162. * referenced later for attaching and detaching a JitsiLocalTrack.
  163. *
  164. * @param {Object} element - DOM element for the component's video display.
  165. * @private
  166. * @returns {void}
  167. */
  168. _setVideoElement(element) {
  169. this._videoElement = element;
  170. }
  171. }
  172. export default Video;