Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Video.js 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import React, { Component } from 'react';
  2. /**
  3. * Component that renders a video element for a passed in video track.
  4. *
  5. * @extends Component
  6. */
  7. class Video extends Component {
  8. /**
  9. * Default values for {@code Video} component's properties.
  10. *
  11. * @static
  12. */
  13. static defaultProps = {
  14. className: '',
  15. id: ''
  16. };
  17. /**
  18. * {@code Video} component's property types.
  19. *
  20. * @static
  21. */
  22. static propTypes = {
  23. /**
  24. * CSS classes to add to the video element.
  25. */
  26. className: React.PropTypes.string,
  27. /**
  28. * The value of the id attribute of the video. Used by the torture tests
  29. * to locate video elements.
  30. */
  31. id: React.PropTypes.string,
  32. /**
  33. * Optional callback to invoke once the video starts playing.
  34. */
  35. onVideoPlaying: React.PropTypes.func,
  36. /**
  37. * The JitsiLocalTrack to display.
  38. */
  39. videoTrack: React.PropTypes.object
  40. };
  41. /**
  42. * Initializes a new {@code Video} instance.
  43. *
  44. * @param {Object} props - The read-only properties with which the new
  45. * instance is to be initialized.
  46. */
  47. constructor(props) {
  48. super(props);
  49. /**
  50. * The internal reference to the DOM/HTML element intended for
  51. * displaying a video. This element may be an HTML video element or a
  52. * temasys video object.
  53. *
  54. * @private
  55. * @type {HTMLVideoElement|Object}
  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. // Add these attributes directly onto the video element so temasys can
  71. // use them when converting the video to an object.
  72. this._videoElement.volume = 0;
  73. this._videoElement.onplaying = this._onVideoPlaying;
  74. this._attachTrack(this.props.videoTrack);
  75. }
  76. /**
  77. * Remove any existing associations between the current video track and the
  78. * component's video element.
  79. *
  80. * @inheritdoc
  81. * @returns {void}
  82. */
  83. componentWillUnmount() {
  84. this._detachTrack(this.props.videoTrack);
  85. }
  86. /**
  87. * Updates the video display only if a new track is added. This component's
  88. * updating is blackboxed from React to prevent re-rendering of video
  89. * element, as the lib uses track.attach(videoElement) instead. Also,
  90. * re-rendering cannot be used with temasys, which replaces video elements
  91. * with an object.
  92. *
  93. * @inheritdoc
  94. * @returns {boolean} - False is always returned to blackbox this component.
  95. * from React.
  96. */
  97. shouldComponentUpdate(nextProps) {
  98. const currentJitsiTrack = this.props.videoTrack
  99. && this.props.videoTrack.jitsiTrack;
  100. const nextJitsiTrack = nextProps.videoTrack
  101. && nextProps.videoTrack.jitsiTrack;
  102. if (currentJitsiTrack !== nextJitsiTrack) {
  103. this._detachTrack(this.props.videoTrack);
  104. this._attachTrack(nextProps.videoTrack);
  105. }
  106. return false;
  107. }
  108. /**
  109. * Renders the video element.
  110. *
  111. * @override
  112. * @returns {ReactElement}
  113. */
  114. render() {
  115. // The wrapping div is necessary because temasys will replace the video
  116. // with an object but react will keep expecting the video element. The
  117. // div gives a constant element for react to keep track of.
  118. return (
  119. <div>
  120. <video
  121. autoPlay = { true }
  122. className = { this.props.className }
  123. id = { this.props.id }
  124. ref = { this._setVideoElement } />
  125. </div>
  126. );
  127. }
  128. /**
  129. * Calls into the passed in track to associate the track with the
  130. * component's video element and render video.
  131. *
  132. * @param {Object} videoTrack - The redux representation of the
  133. * {@code JitsiLocalTrack}.
  134. * @private
  135. * @returns {void}
  136. */
  137. _attachTrack(videoTrack) {
  138. if (!videoTrack || !videoTrack.jitsiTrack) {
  139. return;
  140. }
  141. const updatedVideoElement
  142. = videoTrack.jitsiTrack.attach(this._videoElement);
  143. // Sets the instance variable for the video element again as the element
  144. // maybe have been replaced with a new object by temasys.
  145. this._setVideoElement(updatedVideoElement);
  146. }
  147. /**
  148. * Removes the association to the component's video element from the passed
  149. * in redux representation of jitsi video track to stop the track from
  150. * rendering. With temasys, the video element must still be visible for
  151. * detaching to complete.
  152. *
  153. * @param {Object} videoTrack - The redux representation of the
  154. * {@code JitsiLocalTrack}.
  155. * @private
  156. * @returns {void}
  157. */
  158. _detachTrack(videoTrack) {
  159. // Detach the video element from the track only if it has already
  160. // been attached. This accounts for a special case with temasys
  161. // where if detach is being called before attach, the video
  162. // element is converted to Object without updating this
  163. // component's reference to the video element.
  164. if (this._videoElement
  165. && videoTrack
  166. && videoTrack.jitsiTrack
  167. && videoTrack.jitsiTrack.containers.includes(this._videoElement)) {
  168. videoTrack.jitsiTrack.detach(this._videoElement);
  169. }
  170. }
  171. /**
  172. * Invokes the onvideoplaying callback if defined.
  173. *
  174. * @private
  175. * @returns {void}
  176. */
  177. _onVideoPlaying() {
  178. if (this.props.onVideoPlaying) {
  179. this.props.onVideoPlaying();
  180. }
  181. }
  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;