mpegtsVideo.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <template>
  2. <div class="play-box" >
  3. <div class="play-container"
  4. :style="`background-color: ${bgColor}`">
  5. <video class="player" ref="video" ></video>
  6. </div>
  7. <div v-if="controller" class="play-control ">
  8. <div class="mx-2">
  9. <div class="play-btn" @click="play" v-if="!isPlay" :disabled="!isPush">
  10. {{ $t('play') }}
  11. </div>
  12. <div class="play-btn" @click="pause" v-else :disabled="!isPush">暂停</div>
  13. </div>
  14. <div class="play-btn" @click="replay" >{{ $t('play') }}重新加载</div>
  15. </div>
  16. </div>
  17. </template>
  18. <script>
  19. import mpegTs from 'mpegts.js';
  20. import copy from '@/until/copy'
  21. import {sleep} from "@/until/time";
  22. let videoPlayer = null;
  23. export default {
  24. name: "mpegTsVideo",
  25. props:{
  26. isPush:{},
  27. controller: {default:false},
  28. bgColor: {
  29. default: "#000"
  30. }
  31. },
  32. data(){
  33. return {
  34. isOk: true,
  35. isPlay: false,
  36. loading: false,
  37. playUrl: '',
  38. videoPlayer: null,
  39. tips: '',
  40. fps: 30,
  41. hasAudio: false,
  42. }
  43. },
  44. beforeDestroy() {
  45. this.destroyVideo();
  46. },
  47. methods:{
  48. copyUrl(){
  49. copy(this.playUrl).then(()=>{
  50. this.$message.success('复制成功');
  51. }).catch(err=>{
  52. this.$message.error('复制失败,请手动尝试复制');
  53. })
  54. },
  55. async setPlayUrl(playUrl){
  56. this.playUrl = playUrl;
  57. await this.initVideo();
  58. },
  59. // 初始化视频播放组件
  60. async initVideo(){
  61. //清除
  62. if(!this.playUrl){
  63. return this.$message.warning('请先进行推流')
  64. }
  65. this.isPlay = false;
  66. if(videoPlayer){
  67. this.destroyVideo();
  68. console.log(1)
  69. // 等待2秒
  70. await sleep(2 * 1000);
  71. }
  72. console.log(2)
  73. // 设置直播地址
  74. let player = mpegTs.createPlayer({
  75. type: 'mse', // could also be mpegts, m2ts, flv
  76. isLive: true,
  77. url: this.playUrl,
  78. liveBufferLatencyMaxLatency: 0.5,
  79. enableWorker: true,
  80. enableStashBuffer: true,
  81. hasAudio: this.hasAudio,
  82. fps: this.fps,
  83. fixAudioTimestampGap: false
  84. });
  85. let videoEl = this.$refs.video;
  86. // console.log(videoEl);
  87. player.attachMediaElement(videoEl);
  88. player.load();
  89. player.on(mpegTs.Events.ERROR,(err)=>{
  90. // console.log('---------------------------');
  91. // console.log('------------err---------------');
  92. // console.log('err');
  93. // console.log(err);
  94. this.$emit('error',err);
  95. })
  96. player.on(mpegTs.Events.MEDIA_INFO, (obj)=>{
  97. console.log(`media_info`);
  98. console.log(obj);
  99. })
  100. videoPlayer = player;
  101. },
  102. destroyVideo(){
  103. if(videoPlayer){
  104. console.log(`[销毁播放器] `);
  105. videoPlayer.pause();
  106. videoPlayer.unload();
  107. videoPlayer.detachMediaElement();
  108. videoPlayer.destroy();
  109. videoPlayer = null;
  110. }
  111. },
  112. async play(url,hasAudio = false,fps = 30){
  113. if(url){
  114. console.log(`[播放] 播放新url链接,初始化播放器 hasAudio:${hasAudio} fps:${fps}`);
  115. this.hasAudio = hasAudio;
  116. this.fps = fps || 30;
  117. await this.setPlayUrl(url);
  118. }
  119. console.log(`[播放] 继续播放视频`);
  120. this.isPlay = true;
  121. videoPlayer.play();
  122. },
  123. pause(){
  124. if(!videoPlayer){
  125. console.log(`[暂停] 播放器未初始化`)
  126. return false;
  127. }
  128. this.isPlay = false;
  129. videoPlayer.pause();
  130. },
  131. async replay(){
  132. await this.initVideo();
  133. await this.play();
  134. },
  135. checkBrowser(){
  136. // 检查浏览器是否支持
  137. if(videoPlayer){
  138. return videoPlayer.isSupported();
  139. }else{
  140. return null;
  141. }
  142. }
  143. }
  144. }
  145. </script>
  146. <style scoped >
  147. .play-box{
  148. width: 100%;
  149. height: 100%;
  150. position: relative;
  151. overflow: hidden;
  152. }
  153. .play-box .play-container{
  154. width: 100%;
  155. height: 100%;
  156. position: relative;
  157. }
  158. .play-box .play-container > video{
  159. width: auto;
  160. height: 100%;
  161. }
  162. .play-box .play-control{
  163. position: absolute;
  164. bottom: -40px;
  165. left: 0;
  166. width: 100%;
  167. height: 40px;
  168. display: flex;
  169. background-color: rgba(0,0,0,0.5);
  170. align-items: center;
  171. transition: bottom 0.3s;
  172. }
  173. .play-box:hover .play-control{
  174. bottom: 0;
  175. }
  176. .play-btn{
  177. width: 80px;
  178. height: 30px;
  179. line-height: 30px;
  180. text-align: center;
  181. border-radius: 5px;
  182. background-color: #b0c2d5;
  183. color: #fff;
  184. cursor: pointer;
  185. margin: 0 5px;
  186. }
  187. .play-btn:hover{
  188. background-color: #66b1ff;
  189. }
  190. </style>