use-play.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import '@/assets/css/videojs.scss';
  2. import mpegts from 'mpegts.js';
  3. import videoJs from 'video.js';
  4. import Player from 'video.js/dist/types/player';
  5. import { onMounted, onUnmounted, ref, watch } from 'vue';
  6. import { useAppStore } from '@/store/app';
  7. import { createVideo } from '@/utils';
  8. export * as flvJs from 'flv.js';
  9. export function useFlvPlay() {
  10. // const flvPlayer = ref<flvJs.Player>();
  11. const flvPlayer = ref<mpegts.Player>();
  12. const flvVideoEl = ref<HTMLVideoElement>();
  13. const appStore = useAppStore();
  14. const retryMax = ref(120);
  15. const retry = ref(0);
  16. const retrying = ref(false);
  17. onMounted(() => {});
  18. onUnmounted(() => {
  19. destroyFlv();
  20. });
  21. function destroyFlv() {
  22. if (flvPlayer.value) {
  23. flvPlayer.value.destroy();
  24. flvPlayer.value = undefined;
  25. }
  26. flvVideoEl.value?.remove();
  27. }
  28. watch(
  29. () => appStore.muted,
  30. (newVal) => {
  31. setMuted(newVal);
  32. }
  33. );
  34. function setMuted(val) {
  35. if (flvPlayer.value) {
  36. flvPlayer.value.muted = val;
  37. }
  38. if (flvVideoEl.value) {
  39. flvVideoEl.value.muted = val;
  40. }
  41. }
  42. function startFlvPlay(data: { flvurl: string }) {
  43. console.log('startFlvPlay', data.flvurl);
  44. return new Promise((resolve) => {
  45. function main() {
  46. destroyFlv();
  47. if (mpegts.getFeatureList().mseLivePlayback && mpegts.isSupported()) {
  48. flvPlayer.value = mpegts.createPlayer({
  49. type: 'flv', // could also be mpegts, m2ts, flv
  50. isLive: true,
  51. url: data.flvurl,
  52. });
  53. const videoEl = createVideo({});
  54. videoEl.addEventListener('play', () => {
  55. console.log('flv-play');
  56. });
  57. videoEl.addEventListener('playing', () => {
  58. console.log('flv-playing');
  59. retry.value = 0;
  60. setMuted(appStore.muted);
  61. flvVideoEl.value = videoEl;
  62. resolve('');
  63. });
  64. videoEl.addEventListener('loadedmetadata', () => {
  65. console.log('flv-loadedmetadata');
  66. });
  67. flvPlayer.value.attachMediaElement(videoEl);
  68. flvPlayer.value.load();
  69. flvPlayer.value.on(mpegts.Events.ERROR, () => {
  70. console.error('mpegts消息:mpegts.Events.ERROR');
  71. if (retry.value < retryMax.value && !retrying.value) {
  72. retrying.value = true;
  73. destroyFlv();
  74. setTimeout(() => {
  75. console.error(
  76. '播放flv错误,重新加载,剩余次数:',
  77. retryMax.value - retry.value
  78. );
  79. retry.value += 1;
  80. retrying.value = false;
  81. main();
  82. }, 1000);
  83. }
  84. });
  85. flvPlayer.value.on(mpegts.Events.MEDIA_INFO, () => {
  86. console.log('mpegts消息:mpegts.Events.MEDIA_INFO');
  87. });
  88. try {
  89. console.log(`开始播放flv,muted:${appStore.muted}`);
  90. flvPlayer.value.play();
  91. } catch (err) {
  92. console.error('flv播放失败');
  93. console.log(err);
  94. }
  95. } else {
  96. console.error('不支持flv');
  97. }
  98. }
  99. main();
  100. });
  101. }
  102. return { flvPlayer, flvVideoEl, startFlvPlay, destroyFlv };
  103. }
  104. export function useHlsPlay() {
  105. const hlsPlayer = ref<Player>();
  106. const hlsVideoEl = ref<HTMLVideoElement>();
  107. const appStore = useAppStore();
  108. const retryMax = ref(120);
  109. const retry = ref(0);
  110. const retrying = ref(false);
  111. onMounted(() => {});
  112. onUnmounted(() => {
  113. destroyHls();
  114. });
  115. function destroyHls() {
  116. if (hlsPlayer.value) {
  117. hlsPlayer.value.dispose();
  118. hlsPlayer.value = undefined;
  119. }
  120. hlsVideoEl.value?.remove();
  121. }
  122. function setMuted(val) {
  123. console.log('setMuted', val);
  124. if (hlsVideoEl.value) {
  125. hlsVideoEl.value.muted = val;
  126. }
  127. if (hlsPlayer.value) {
  128. hlsPlayer.value.muted(val);
  129. }
  130. }
  131. watch(
  132. () => appStore.muted,
  133. (newVal) => {
  134. setMuted(newVal);
  135. }
  136. );
  137. function startHlsPlay(data: { hlsurl: string }) {
  138. return new Promise((resolve) => {
  139. function main() {
  140. console.log('startHlsPlay', data.hlsurl);
  141. destroyHls();
  142. const videoEl = createVideo({ muted: appStore.muted, autoplay: true });
  143. hlsPlayer.value = videoJs(
  144. videoEl,
  145. {
  146. sources: [
  147. {
  148. src: data.hlsurl,
  149. type: 'application/x-mpegURL',
  150. },
  151. ],
  152. },
  153. function () {
  154. try {
  155. console.log(`开始播放hls,muted:${appStore.muted}`);
  156. hlsPlayer.value?.play();
  157. } catch (err) {
  158. console.error('hls播放失败');
  159. console.log(err);
  160. }
  161. }
  162. );
  163. hlsPlayer.value?.on('error', () => {
  164. console.log('hls-error');
  165. if (retry.value < retryMax.value && !retrying.value) {
  166. retrying.value = true;
  167. setTimeout(() => {
  168. console.error(
  169. '播放hls错误,重新加载,剩余次数:',
  170. retryMax.value - retry.value
  171. );
  172. retry.value += 1;
  173. retrying.value = false;
  174. main();
  175. }, 1000);
  176. }
  177. });
  178. hlsPlayer.value?.on('play', () => {
  179. console.log('hls-play');
  180. // console.log(hlsPlayer.value?.videoHeight()); // 获取到的是0!
  181. });
  182. hlsPlayer.value?.on('playing', () => {
  183. console.log('hls-playing');
  184. setMuted(appStore.muted);
  185. retry.value = 0;
  186. // console.log(hlsPlayer.value?.videoHeight()); // 获取到的是正确的!
  187. const childNodes = hlsPlayer.value?.el().childNodes;
  188. if (childNodes) {
  189. childNodes.forEach((item) => {
  190. if (item.nodeName.toLowerCase() === 'video') {
  191. // @ts-ignore
  192. hlsVideoEl.value = item;
  193. }
  194. });
  195. }
  196. hlsVideoEl.value = videoEl;
  197. resolve('');
  198. });
  199. hlsPlayer.value?.on('loadedmetadata', () => {
  200. console.log('hls-loadedmetadata');
  201. });
  202. }
  203. main();
  204. });
  205. }
  206. return { hlsPlayer, hlsVideoEl, startHlsPlay, destroyHls };
  207. }