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.8KB

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