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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. }
  87. /**
  88. * Remove any existing associations between the current video track and the
  89. * component's video element.
  90. *
  91. * @inheritdoc
  92. * @returns {void}
  93. */
  94. componentWillUnmount() {
  95. this._detachTrack(this.props.videoTrack);
  96. }
  97. /**
  98. * Updates the video display only if a new track is added. This component's
  99. * updating is blackboxed from React to prevent re-rendering of video
  100. * element, as the lib uses {@code track.attach(videoElement)} instead.
  101. *
  102. * @inheritdoc
  103. * @returns {boolean} - False is always returned to blackbox this component
  104. * from React.
  105. */
  106. shouldComponentUpdate(nextProps: Props) {
  107. const currentJitsiTrack = this.props.videoTrack
  108. && this.props.videoTrack.jitsiTrack;
  109. const nextJitsiTrack = nextProps.videoTrack
  110. && nextProps.videoTrack.jitsiTrack;
  111. if (currentJitsiTrack !== nextJitsiTrack) {
  112. this._detachTrack(this.props.videoTrack);
  113. this._attachTrack(nextProps.videoTrack);
  114. }
  115. return false;
  116. }
  117. /**
  118. * Renders the video element.
  119. *
  120. * @override
  121. * @returns {ReactElement}
  122. */
  123. render() {
  124. return (
  125. <video
  126. autoPlay = { this.props.autoPlay }
  127. className = { this.props.className }
  128. id = { this.props.id }
  129. playsInline = { this.props.playsinline }
  130. ref = { this._setVideoElement } />
  131. );
  132. }
  133. /**
  134. * Calls into the passed in track to associate the track with the
  135. * component's video element and render video.
  136. *
  137. * @param {Object} videoTrack - The redux representation of the
  138. * {@code JitsiLocalTrack}.
  139. * @private
  140. * @returns {void}
  141. */
  142. _attachTrack(videoTrack) {
  143. if (!videoTrack || !videoTrack.jitsiTrack) {
  144. return;
  145. }
  146. videoTrack.jitsiTrack.attach(this._videoElement);
  147. }
  148. /**
  149. * Removes the association to the component's video element from the passed
  150. * in redux representation of jitsi video track to stop the track from
  151. * rendering.
  152. *
  153. * @param {Object} videoTrack - The redux representation of the
  154. * {@code JitsiLocalTrack}.
  155. * @private
  156. * @returns {void}
  157. */
  158. _detachTrack(videoTrack) {
  159. if (this._videoElement && videoTrack && videoTrack.jitsiTrack) {
  160. videoTrack.jitsiTrack.detach(this._videoElement);
  161. }
  162. }
  163. _onVideoPlaying: () => void;
  164. /**
  165. * Invokes the onvideoplaying callback if defined.
  166. *
  167. * @private
  168. * @returns {void}
  169. */
  170. _onVideoPlaying() {
  171. if (this.props.onVideoPlaying) {
  172. this.props.onVideoPlaying();
  173. }
  174. }
  175. _setVideoElement: () => void;
  176. /**
  177. * Sets an instance variable for the component's video element so it can be
  178. * referenced later for attaching and detaching a JitsiLocalTrack.
  179. *
  180. * @param {Object} element - DOM element for the component's video display.
  181. * @private
  182. * @returns {void}
  183. */
  184. _setVideoElement(element) {
  185. this._videoElement = element;
  186. }
  187. }
  188. export default Video;