mirror of
https://github.com/langyuxiansheng/vue-aliplayer-v2.git
synced 2026-06-03 20:20:23 +08:00
fix: 升级vue3
This commit is contained in:
parent
cdf70ab208
commit
15c784daef
@ -1,2 +0,0 @@
|
|||||||
> 1%
|
|
||||||
last 2 versions
|
|
||||||
23
.eslintrc.js
23
.eslintrc.js
@ -1,23 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
browser: true,
|
|
||||||
es6: true
|
|
||||||
},
|
|
||||||
'extends': [
|
|
||||||
'plugin:vue/essential',
|
|
||||||
'eslint:recommended'
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
parser: 'babel-eslint'
|
|
||||||
},
|
|
||||||
|
|
||||||
globals: {
|
|
||||||
'Aliplayer': false
|
|
||||||
},
|
|
||||||
}
|
|
||||||
268
GITHUB_ISSUES_TODO.md
Normal file
268
GITHUB_ISSUES_TODO.md
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
# GitHub Issues Todo
|
||||||
|
|
||||||
|
Fetched from `langyuxiansheng/vue-aliplayer-v2` open issues on 2026-05-23.
|
||||||
|
|
||||||
|
Source: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- Open issues recorded: 25
|
||||||
|
- Main themes: Vue 3 compatibility, SDK loading/lifecycle, FLV/HLS/RTMP playback, Aliplayer SDK version drift, skin/custom UI configuration, documentation gaps.
|
||||||
|
- Implementation pass on 2026-05-23: Vue 3 rewrite landed, SDK default updated to the new `imp-web-player` path, wrapper-level lifecycle/loading/playback helpers were added. Items marked "Code status" below are handled in this repository unless noted as upstream/documentation-only.
|
||||||
|
|
||||||
|
## Compatibility And Packaging
|
||||||
|
|
||||||
|
### #34 please support vue3.x
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/34
|
||||||
|
- Created: 2020-12-08
|
||||||
|
- Comments: 3
|
||||||
|
- Problem: users request Vue 3 support.
|
||||||
|
- Notes: comments mention a third-party Vue 3/Vite fork/package `vue-aliplayer-v3`; current project is Vue 2 based.
|
||||||
|
- Follow-up: decide whether to add Vue 3 support in this package, publish a separate Vue 3 package, or document Vue 2-only support.
|
||||||
|
- Code status: fixed in v2.0.0 rewrite. Vue 2 users must stay on 1.x.
|
||||||
|
|
||||||
|
### #35 安装之后引用就直接报这个问题
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/35
|
||||||
|
- Created: 2020-12-23
|
||||||
|
- Comments: 3
|
||||||
|
- Problem: Vue 3 usage throws `Cannot read property '_c' of undefined` from `vue-aliplayer-v2.umd.min.js`.
|
||||||
|
- Notes: maintainer identified likely cause as Vue version mismatch; overlaps with #34.
|
||||||
|
- Follow-up: treat as Vue 3 compatibility/package-entry issue.
|
||||||
|
- Code status: fixed by replacing the Vue 2 UMD build with Vue 3/Vite library output.
|
||||||
|
|
||||||
|
### #65 VueAliplayerV2在vue中使用报错
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/65
|
||||||
|
- Created: 2022-06-12
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: user reports usage error with screenshot only.
|
||||||
|
- Notes: another user reported the same issue in 2023.
|
||||||
|
- Follow-up: inspect screenshot manually when triaging; likely packaging/import/runtime compatibility.
|
||||||
|
- Code status: likely fixed by Vue 3 package rewrite and typed exports; still needs reporter repro if screenshot covers another error.
|
||||||
|
|
||||||
|
### #45 关于浏览器兼容的问题
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/45
|
||||||
|
- Created: 2021-03-23
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: works in Chrome 89, player component does not display in Chrome 59.
|
||||||
|
- Notes: current wrapper relies on upstream Aliplayer SDK compatibility.
|
||||||
|
- Follow-up: define supported browser matrix and test whether transpilation/polyfills or SDK version is the blocker.
|
||||||
|
- Code status: documented as upstream SDK/browser support. v2 build targets modern Vue 3/Vite environments.
|
||||||
|
|
||||||
|
### #46 请问,我使用uniapp安装aliplayerV2的问题
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/46
|
||||||
|
- Created: 2021-03-25
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: using npm install in uni-app, player buttons/components do not show.
|
||||||
|
- Notes: maintainer had not tested uni-app.
|
||||||
|
- Follow-up: decide whether uni-app is supported; if yes, add setup notes and a minimal repro.
|
||||||
|
- Code status: not claimed as fixed. Needs a uni-app repro because this package targets Vue 3 web apps.
|
||||||
|
|
||||||
|
### #70 建议升级阿里云播放器到最新版
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/70
|
||||||
|
- Created: 2023-04-12
|
||||||
|
- Comments: 0
|
||||||
|
- Problem: default SDK is outdated; user changed CSS/JS defaults to Aliplayer `2.15.2`.
|
||||||
|
- Notes: user also mentions missing source maps because Aliplayer is closed source.
|
||||||
|
- Follow-up: verify latest stable Aliplayer SDK URL, update defaults if safe, and document how to override SDK URLs.
|
||||||
|
- Code status: fixed. Default SDK now uses `apsara-media-box/imp-web-player/2.37.0`; `sdkVersion`, `cssLink`, and `scriptSrc` are configurable.
|
||||||
|
|
||||||
|
## SDK Loading And Lifecycle
|
||||||
|
|
||||||
|
### #71 优化建议
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/71
|
||||||
|
- Created: 2024-08-02
|
||||||
|
- Comments: 2
|
||||||
|
- Problem: each created player reportedly adds another CSS and JS resource.
|
||||||
|
- Notes: comment references newer `apsara-media-box/imp-web-player/2.16.3` resource URLs and a multi-player example.
|
||||||
|
- Follow-up: reproduce with multiple create/destroy cycles and verify whether duplicate resource tags appear under current component logic.
|
||||||
|
- Code status: fixed in shared SDK loader. It caches CSS/JS by URL and avoids duplicate tags for multiple players.
|
||||||
|
|
||||||
|
### #62 多屏播放后,只销毁最后一个播放实例
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/62
|
||||||
|
- Created: 2022-03-25
|
||||||
|
- Comments: 2
|
||||||
|
- Problem: in `v-for`, clearing the list only destroys the last player instance.
|
||||||
|
- Notes: reporter says FLV did not reproduce, HLS did reproduce.
|
||||||
|
- Follow-up: test multi-instance destroy with HLS and inspect player ID/ref/lifecycle handling.
|
||||||
|
- Code status: improved. Component now guards async init after unmount and disposes each instance independently; still needs real HLS multi-player regression test.
|
||||||
|
|
||||||
|
### #69 Uncaught TypeError: s._options is null
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/69
|
||||||
|
- Created: 2023-03-29
|
||||||
|
- Comments: 0
|
||||||
|
- Problem: runtime error `s._options is null`, screenshot only.
|
||||||
|
- Follow-up: inspect screenshot and try to reproduce around destroy/re-init or options mutation.
|
||||||
|
- Code status: improved. Init is token-guarded and avoids creating stale players after fast option/source changes.
|
||||||
|
|
||||||
|
## Playback Failures And Stream Behavior
|
||||||
|
|
||||||
|
### #11 rtmp html5模式下不能播放
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/11
|
||||||
|
- Created: 2020-06-10
|
||||||
|
- Comments: 3
|
||||||
|
- Problem: RTMP cannot play in HTML5 mode after Flash deprecation.
|
||||||
|
- Notes: comment says RTMP only works with Flash; another suggests FLV.js.
|
||||||
|
- Follow-up: document RTMP limitation clearly; avoid promising HTML5 RTMP support unless using another playback strategy.
|
||||||
|
- Code status: documented limitation. RTMP H5 support is not fixed in wrapper.
|
||||||
|
|
||||||
|
### #21 直播,不能播放flv格式的视频
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/21
|
||||||
|
- Created: 2020-08-10
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: FLV live stream fails both by `source` and dynamic `loadByUrl`.
|
||||||
|
- Notes: maintainer suggested validating stream in VLC and checking Aliplayer config.
|
||||||
|
- Follow-up: create verified FLV live test case and document required options.
|
||||||
|
- Code status: improved. Wrapper infers `format: 'flv'`; `lowLatency` adds FLV live buffer defaults. Needs real FLV source validation.
|
||||||
|
|
||||||
|
### #24 mp4格式视频加载错误4400
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/24
|
||||||
|
- Created: 2020-09-27
|
||||||
|
- Comments: 4
|
||||||
|
- Problem: large or special MP4 URL reports error 4400; user says autoplay is false but play still appears to trigger.
|
||||||
|
- Notes: maintainer suspected URL permissions/cross-origin/path encoding; reporter later said the URL contains Chinese characters.
|
||||||
|
- Follow-up: test encoded vs unencoded URLs, autoplay false behavior, and error handling for cross-origin/private MP4.
|
||||||
|
- Code status: improved. Wrapper now `encodeURI`s source URLs by default to handle Chinese filenames. Cross-origin/private URL failures remain source/server issues.
|
||||||
|
|
||||||
|
### #37 发现m3u8视频播放时的问题
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/37
|
||||||
|
- Created: 2021-01-07
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: M3U8 quality switching is delayed; after switching and refreshing, playback fails.
|
||||||
|
- Follow-up: reproduce with multi-quality M3U8 source and inspect whether wrapper re-init/load flow loses format or quality state.
|
||||||
|
- Code status: improved. Wrapper infers source format and rebuilds player on cross-format changes instead of always calling `loadByUrl`.
|
||||||
|
|
||||||
|
### #52 flv直播刷新页面视频卡住
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/52
|
||||||
|
- Created: 2021-06-16
|
||||||
|
- Comments: 3
|
||||||
|
- Problem: FLV live video gets stuck after page refresh.
|
||||||
|
- Notes: reporter confirmed issue was still unresolved in 2021.
|
||||||
|
- Follow-up: include in FLV live repro matrix with #21 and #68.
|
||||||
|
- Code status: improved by FLV format inference, async init guards, and `lowLatency`; still needs real stream repro.
|
||||||
|
|
||||||
|
### #68 播放Flv视频直播时,时间长了后会延迟几分钟
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/68
|
||||||
|
- Created: 2022-12-17
|
||||||
|
- Comments: 0
|
||||||
|
- Problem: FLV live stream accumulates several minutes of latency over time.
|
||||||
|
- Follow-up: check Aliplayer FLV buffer options such as stash buffer settings and live latency handling.
|
||||||
|
- Code status: improved. `lowLatency` applies `enableStashBufferForFlv: false` and `stashInitialSizeForFlv: 128` unless explicitly overridden.
|
||||||
|
|
||||||
|
## Playback APIs And Source Modes
|
||||||
|
|
||||||
|
### #43 vid+palyauth播放问题
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/43
|
||||||
|
- Created: 2021-03-06
|
||||||
|
- Comments: 5
|
||||||
|
- Problem: `replayByVidAndPlayAuth` appears undefined from both `getPlayer()` and component ref.
|
||||||
|
- Notes: later comment says methods like `replay()` and `pause()` were also undefined; maintainer notes multiple refs become arrays; user later resolved.
|
||||||
|
- Follow-up: improve docs for `$refs` in single vs multiple-player usage and when methods are available.
|
||||||
|
- Code status: fixed for Vue 3 docs. README now shows typed `ref<VueAliplayerV2Expose | null>`.
|
||||||
|
|
||||||
|
### #49 这个不支持vid+playauth播放吗
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/49
|
||||||
|
- Created: 2021-05-18
|
||||||
|
- Comments: 3
|
||||||
|
- Problem: question about `vid + playauth` playback support.
|
||||||
|
- Notes: comment says it works when adding `encryptType: 1`; later user asks what else is required.
|
||||||
|
- Follow-up: add working `vid + playauth` example and option notes.
|
||||||
|
- Code status: documented. `vid + playauth` is supported through `options`; ref method remains exposed.
|
||||||
|
|
||||||
|
## UI, Skin, And Extension Features
|
||||||
|
|
||||||
|
### #53 播放按钮
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/53
|
||||||
|
- Created: 2021-06-21
|
||||||
|
- Comments: 14
|
||||||
|
- Problem: users ask how to center play button, configure quality/subtitle options, change cover, and adjust progress/button colors.
|
||||||
|
- Notes: maintainer answered that `skinLayout` must be placed inside `options`; example uses `skinLayout: [{ name: 'bigPlayButton', align: 'cc' }]`.
|
||||||
|
- Follow-up: add skin customization examples to README.
|
||||||
|
- Code status: partially documented through options passthrough. More visual skin examples can be added later.
|
||||||
|
|
||||||
|
### #55 请问我要把清晰度切换单独放到设置外面要怎么弄呢?
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/55
|
||||||
|
- Created: 2021-06-22
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: user wants quality switch outside the settings menu.
|
||||||
|
- Notes: maintainer pointed to Aliplayer skin settings docs.
|
||||||
|
- Follow-up: document whether this is possible through `skinLayout` or requires custom components.
|
||||||
|
- Code status: documented as Aliplayer skin/custom component responsibility.
|
||||||
|
|
||||||
|
### #57 自定义组件
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/57
|
||||||
|
- Created: 2021-07-06
|
||||||
|
- Comments: 4
|
||||||
|
- Problem: user asks whether Aliplayer custom component API is supported for a playlist.
|
||||||
|
- Notes: maintainer says SDK should support it, but another user says adding `components` in `options` does not work unless custom component JS is separately loaded.
|
||||||
|
- Follow-up: verify custom component loading order and provide an example if supported.
|
||||||
|
- Code status: improved. Added `componentScripts` to load custom component scripts before player init; README includes example.
|
||||||
|
|
||||||
|
### #61 播放失败页面自定义
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/61
|
||||||
|
- Created: 2021-09-24
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: clicking refresh on the player error page refreshes the whole page; user wants local refresh or custom refresh handler.
|
||||||
|
- Notes: maintainer says the error page comes from Aliplayer.
|
||||||
|
- Follow-up: check whether SDK exposes error UI customization or whether wrapper can expose a local retry pattern.
|
||||||
|
- Code status: improved. Added `reload()` / `retry()` exposed methods for local retry; SDK error UI itself remains upstream.
|
||||||
|
|
||||||
|
### #67 跑马灯功能可以用吗
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/67
|
||||||
|
- Created: 2022-10-08
|
||||||
|
- Comments: 0
|
||||||
|
- Problem: user asks whether marquee/watermark scrolling text is available.
|
||||||
|
- Follow-up: verify Aliplayer support and document unsupported/supported approach.
|
||||||
|
- Code status: documented via `componentScripts` + `options.components`; availability depends on the loaded Aliplayer custom component.
|
||||||
|
|
||||||
|
### #59 如何关闭track
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/59
|
||||||
|
- Created: 2021-08-20
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: player sends tracking POST requests to `https://videocloud.cn-hangzhou.log.aliyuncs.com/logstores/newplayer/track`; user wants to disable.
|
||||||
|
- Notes: a comment suggests deleting `postWithHeader`, which is not a clean wrapper-level solution.
|
||||||
|
- Follow-up: find official SDK option, if any; otherwise document limitation.
|
||||||
|
- Code status: opt-in mitigation added. `disableTracking` can block known Aliplayer tracking URLs at wrapper level.
|
||||||
|
|
||||||
|
## Format And Capability Questions
|
||||||
|
|
||||||
|
### #60 能播vr视频或者vr直播吗
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/60
|
||||||
|
- Created: 2021-09-16
|
||||||
|
- Comments: 1
|
||||||
|
- Problem: asks whether VR video or VR live can be played.
|
||||||
|
- Notes: maintainer had not tested.
|
||||||
|
- Follow-up: verify upstream Aliplayer capability and document scope.
|
||||||
|
- Code status: documentation-only. Wrapper passes options through but does not implement VR rendering itself.
|
||||||
|
|
||||||
|
### #66 支持AVI 格式的视频吗?
|
||||||
|
|
||||||
|
- Link: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/66
|
||||||
|
- Created: 2022-09-07
|
||||||
|
- Comments: 0
|
||||||
|
- Problem: asks whether AVI format is supported.
|
||||||
|
- Follow-up: document supported formats according to upstream Aliplayer/browser support.
|
||||||
|
- Code status: documented format scope. AVI is not claimed as supported by this wrapper.
|
||||||
706
README.md
706
README.md
@ -1,512 +1,296 @@
|
|||||||
# vue-alipayer-v2
|
# vue-aliplayer-v2
|
||||||
|
|
||||||
## 感谢每一位支持开源的朋友. 这是一个基于 Alipayer 开发并封装成 vue 组件的播放器.
|
基于阿里云 Aliplayer SDK 的 Vue 3 播放器组件。可通过 Aliplayer 官方能力播放 mp4、m3u8、flv、直播流、加密点播、清晰度切换和直播时移等场景。
|
||||||
|
|
||||||
### vue 中使用 Alipayer,播放 rtmp,m3u8,mp4 视频
|
> v2 从 Vue 3 + Vite 重构开始,不再兼容 Vue 2。Vue 2 项目请继续安装 `vue-aliplayer-v2@1.x`。
|
||||||
|
|
||||||
#### [本项目在线演示](https://langyuxiansheng.github.io/vue-aliplayer-v2/)
|
## 在线演示
|
||||||
|
|
||||||
#### [阿里云播放器在线演示](https://player.alicdn.com/aliplayer/index.html)
|
- 项目演示:https://langyuxiansheng.github.io/vue-aliplayer-v2/
|
||||||
|
- 阿里云播放器演示:https://player.alicdn.com/aliplayer/index.html
|
||||||
|
|
||||||
> 假如此轮子对你有帮助,请顺手 star 一下吧.o(_ ̄︶ ̄_)o
|
## 安装
|
||||||
|
|
||||||
## 1.安装使用! 下载安装 npm 包
|
```bash
|
||||||
|
npm i vue-aliplayer-v2
|
||||||
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm i vue-aliplayer-v2 --save
|
|
||||||
or
|
|
||||||
yarn add vue-aliplayer-v2
|
yarn add vue-aliplayer-v2
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 全局注册 main.js
|
## 全局注册
|
||||||
|
|
||||||
```javascript
|
```ts
|
||||||
import VueAliplayerV2 from "vue-aliplayer-v2";
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import VueAliplayerV2 from 'vue-aliplayer-v2';
|
||||||
|
|
||||||
Vue.use(VueAliplayerV2);
|
const app = createApp(App);
|
||||||
|
|
||||||
//可选全局配置
|
app.use(VueAliplayerV2, {
|
||||||
//Vue.use(VueAliplayerV2,{
|
// 默认使用阿里云 Web 播放器 SDK 2.37.0,新版 SDK 走 imp-web-player 资源路径
|
||||||
// cssLink: 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css',
|
sdkVersion: '2.37.0',
|
||||||
// scriptSrc: 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'
|
// 可选:覆盖完整 SDK 地址
|
||||||
//});
|
cssLink: 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.37.0/skins/default/aliplayer-min.css',
|
||||||
|
scriptSrc: 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.37.0/aliplayer-min.js'
|
||||||
|
});
|
||||||
|
|
||||||
|
app.mount('#app');
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 局部注册 App.vue
|
## 局部注册
|
||||||
|
|
||||||
```javascript
|
```vue
|
||||||
//推荐第一种(仅v1.2.3)及以上的版本可用
|
|
||||||
import VueAliplayerV2 from "vue-aliplayer-v2";
|
|
||||||
components: {
|
|
||||||
VueAliplayerV2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//或者
|
|
||||||
components: {
|
|
||||||
VueAliplayerV2: VueAliplayerV2.Player;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2.组件中使用
|
|
||||||
|
|
||||||
### 组件模板使用,下面的视频连接仅供演示测试.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<VueAliplayerV2
|
||||||
<template v-if="!isShowMultiple && show">
|
ref="playerRef"
|
||||||
<vue-aliplayer-v2
|
|
||||||
:source="source"
|
:source="source"
|
||||||
ref="VueAliplayerV2"
|
|
||||||
:options="options"
|
:options="options"
|
||||||
|
:license="license"
|
||||||
|
low-latency
|
||||||
|
@ready="handleReady"
|
||||||
|
@error="handleError"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="isShowMultiple && show" class="show-multiple">
|
|
||||||
<template v-for="x in 5">
|
|
||||||
<vue-aliplayer-v2
|
|
||||||
class="multiple-player"
|
|
||||||
:key="x"
|
|
||||||
:source="source"
|
|
||||||
ref="VueAliplayerV2"
|
|
||||||
:options="options"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<p class="remove-text" v-if="!show">播放器已销毁!</p>
|
|
||||||
<div class="player-btns">
|
|
||||||
<template v-if="!isShowMultiple && show">
|
|
||||||
<span @click="play()">播放</span>
|
|
||||||
<span @click="pause()">暂停</span>
|
|
||||||
<span @click="replay()">重播</span>
|
|
||||||
<span @click="getCurrentTime()">播放时刻</span>
|
|
||||||
<span @click="getStatus()">获取播放器状态</span>
|
|
||||||
</template>
|
|
||||||
<span @click="show = !show">{{ show ? '销毁' : '重载' }}</span>
|
|
||||||
<span @click="options.isLive = !options.isLive"
|
|
||||||
>{{ options.isLive ? '切换普通模式' : '切换直播模式' }}</span
|
|
||||||
>
|
|
||||||
<span @click="showMultiple()"
|
|
||||||
>{{isShowMultiple ? '显示1个播放器' : '显示多个播放器'}}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="source-box">
|
|
||||||
<span class="source-label">选择播放源(支持动态切换):</span>
|
|
||||||
<select v-model="source" name="source" id="source">
|
|
||||||
<option value="//player.alicdn.com/video/aliyunmedia.mp4"
|
|
||||||
>播放源1</option
|
|
||||||
>
|
|
||||||
<option value="//yunqivedio.alicdn.com/user-upload/nXPDX8AASx.mp4"
|
|
||||||
>播放源2</option
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
value="//tbm-auth.alicdn.com/e7qHgLdugbzzKh2eW0J/kXTgBkjvNXcERYxh2PA@@hd_hq.mp4?auth_key=1584519814-0-0-fc98b2738f331ff015f7bf5c62394888"
|
|
||||||
>播放源3</option
|
|
||||||
>
|
|
||||||
<option value="//ivi.bupt.edu.cn/hls/cctv1.m3u8">直播播放源4</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="source-box">
|
|
||||||
<span class="source-label">输入播放源(支持动态切换):</span>
|
|
||||||
<input class="source-input" type="text" v-model="source" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
options: {
|
|
||||||
// source:'//player.alicdn.com/video/aliyunmedia.mp4',
|
|
||||||
isLive: true, //切换为直播流的时候必填
|
|
||||||
// format: 'm3u8' //切换为直播流的时候必填
|
|
||||||
},
|
|
||||||
source: "//player.alicdn.com/video/aliyunmedia.mp4",
|
|
||||||
// source: '//ivi.bupt.edu.cn/hls/cctv1.m3u8',
|
|
||||||
show: true,
|
|
||||||
isShowMultiple: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
<script setup lang="ts">
|
||||||
play() {
|
import { reactive, ref } from 'vue';
|
||||||
this.$refs.VueAliplayerV2.play();
|
import VueAliplayerV2, {
|
||||||
},
|
type AliplayerLicense,
|
||||||
|
type AliplayerOptions,
|
||||||
|
type VueAliplayerV2Expose
|
||||||
|
} from 'vue-aliplayer-v2';
|
||||||
|
|
||||||
pause() {
|
const playerRef = ref<VueAliplayerV2Expose | null>(null);
|
||||||
this.$refs.VueAliplayerV2.pause();
|
const source = ref('//player.alicdn.com/video/aliyunmedia.mp4');
|
||||||
},
|
const license = ref<AliplayerLicense | null>(null);
|
||||||
|
const options = reactive<AliplayerOptions>({
|
||||||
|
autoplay: true,
|
||||||
|
isLive: false,
|
||||||
|
useH5Prism: true
|
||||||
|
});
|
||||||
|
|
||||||
replay() {
|
function handleReady() {
|
||||||
this.$refs.VueAliplayerV2.replay();
|
playerRef.value?.play();
|
||||||
},
|
|
||||||
|
|
||||||
getCurrentTime() {
|
|
||||||
// this.$refs.VueAliplayerV2.getCurrentTime();
|
|
||||||
this.source = "http://ivi.bupt.edu.cn/hls/cctv1.m3u8";
|
|
||||||
},
|
|
||||||
|
|
||||||
getStatus() {
|
|
||||||
const status = this.$refs.VueAliplayerV2.getStatus();
|
|
||||||
console.log(`getStatus:`, status);
|
|
||||||
alert(`getStatus:${status}`);
|
|
||||||
},
|
|
||||||
|
|
||||||
showMultiple() {
|
|
||||||
this.isShowMultiple = !this.isShowMultiple;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style lang="less">
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
.remove-text {
|
|
||||||
text-align: center;
|
function handleError(error: unknown) {
|
||||||
padding: 20px;
|
console.log('player error', error);
|
||||||
font-size: 24px;
|
|
||||||
}
|
}
|
||||||
.show-multiple {
|
|
||||||
display: flex;
|
|
||||||
.multiple-player {
|
|
||||||
width: calc(100% / 4);
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.player-btns {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
span {
|
|
||||||
margin: 0 auto;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 5px 10px;
|
|
||||||
width: 150px;
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
background: #e1e1e1;
|
|
||||||
border-radius: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.source-box {
|
|
||||||
padding: 5px 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
.source-label {
|
|
||||||
margin-right: 20px;
|
|
||||||
font-size: 16px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#source {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.source-input {
|
|
||||||
margin-top: 10px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
width: 80%;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3.功能与配置
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
props:{
|
|
||||||
|
|
||||||
forbidFastForward: { //禁止拖拽快进
|
|
||||||
required: false,
|
|
||||||
type: [Boolean],
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
|
|
||||||
options: { //配置项 (options.source 不支持动态切换,需要动态切换请直接使用source)
|
|
||||||
required: false,
|
|
||||||
type: [Object],
|
|
||||||
default: () => null
|
|
||||||
},
|
|
||||||
|
|
||||||
source: { //播放源(此属性存在则优先于options.source) 支持动态切换,目前只支持同种格式(mp4/flv/m3u8)之间切换。暂不支持直播rtmp流切换。
|
|
||||||
required: false,
|
|
||||||
type: [Object],
|
|
||||||
default: () => null
|
|
||||||
},
|
|
||||||
|
|
||||||
cssLink:{ //css版本源
|
|
||||||
required: false,
|
|
||||||
type: [String],
|
|
||||||
default: `https://g.alicdn.com/de/prismplayer/2.9.7/skins/default/aliplayer-min.css`
|
|
||||||
},
|
|
||||||
scriptSrc:{ //js版本源
|
|
||||||
required: false,
|
|
||||||
type: [String],
|
|
||||||
default: `https://g.alicdn.com/de/prismplayer/2.9.7/aliplayer-min.js`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.1 配置项 options 属性
|
|
||||||
|
|
||||||
可以参考 [属性和接口说明](https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.6.1085.36fc6fc57WKZ5P)
|
|
||||||
|
|
||||||
| 名称 | 类型 | 说明 |
|
|
||||||
| :----------------------- | :-----------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| source | String | 视频播放地址 url:单独 url。默认状态,表示使用 vid+playauth。source 播放方式优先级最高。source 支持多清晰度设置:source:’{“HD”:”address1”,”SD”:”address2”’,详情参见多清晰度播放。 |
|
|
||||||
| vid | String | 媒体转码服务的媒体 Id。 |
|
|
||||||
| playauth | String | 播放权证,如何得到参见获取 playauth。 |
|
|
||||||
| height | String | 播放器高度,可形如‘100%’或者‘100px’,chrome 浏览器下 flash 播放器分别不能小于 397x297。 |
|
|
||||||
| width | String | 播放器宽度,可形如‘100%’或者‘100px’,chrome 浏览器下 flash 播放器分别不能小于 397x297。 |
|
|
||||||
| videoWidth | String | 视频宽度,仅 h5 支持。详情参见旋转和镜像。 |
|
|
||||||
| videoHeight | String | 视频高度,仅 h5 支持。详情参见旋转和镜像。 |
|
|
||||||
| preload | Boolean | 播放器自动加载,目前仅 h5 可用。 |
|
|
||||||
| cover | String | 播放器默认封面图片,请填写正确的图片 url 地址。需要 autoplay 为’false’时,才生效。Flash 播放器封面也需要开启允许跨域访问。 |
|
|
||||||
| isLive | Boolean | 播放内容是否为直播,直播时会禁止用户拖动进度条。 |
|
|
||||||
| autoplay | Boolean | 播放器是否自动播放,在移动端 autoplay 属性会失效。Safari11 不会自动开启自动播放如何开启。 |
|
|
||||||
| rePlay | Boolean | 播放器自动循环播放。 |
|
|
||||||
| useH5Prism | Boolean | 指定使用 H5 播放器。 |
|
|
||||||
| useFlashPrism | Boolean | 指定使用 Flash 播放器。 |
|
|
||||||
| playsinline | Boolean | H5 是否内置播放,有的 Android 浏览器不起作用。 |
|
|
||||||
| showBuffer | Boolean | 显示播放时缓冲图标,默认 true。 |
|
|
||||||
| skinRes | Url | 说明:皮肤图片,不建议随意修改该字段,如要修改,请参照皮肤定制。 |
|
|
||||||
| skinLayout | Array Boolean | 说明:功能组件布局配置,不传该字段使用默认布局。传 false 隐藏所有功能组件,请参照皮肤定制。 |
|
|
||||||
| controlBarVisibility | String | 控制面板的实现,默认为‘hover’。可选的值为:‘click’、‘hover’、‘always’。 |
|
|
||||||
| showBarTime | String | 控制栏自动隐藏时间(ms)。 |
|
|
||||||
| extraInfo | String | 说明:JSON 串用于定制性接口参数。 |
|
|
||||||
| > | > | 1.“fullTitle”:“测试页面”全屏时显示视频标题(仅 flash 支持)。 |
|
|
||||||
| > | > | 2. “m3u8BufferLength”:“30”播放 m3u8 时加载缓存 ts 文件长度单位(秒)(仅 flash 支持)。 |
|
|
||||||
| > | > | 3. “liveStartTime”:“2016/08/17 12:00:00”,直播开始时间,用于提示直播未开始(仅 flash 支持)。 |
|
|
||||||
| > | > | 4. “liveOverTime”:“2016/08/17 14:00:00”,直播结束时间,用于提示直播结束(仅 flash 支持)。 |
|
|
||||||
| enableSystemMenu | Boolean | 是否允许系统右键菜单显示,默认为 false。 |
|
|
||||||
| format | String | 指定播放地址格式,只有使用 vid 的播放方式时支持,可选值为’mp4’、’m3u8’、’flv’、’mp3’,默认为空,仅 H5 支持。 |
|
|
||||||
| mediaType | String | 指定返回音频还是视频,只有使用 vid 的播放方式时支持。可选值为’video’和’audio’,默认为’video’,‘audio’主要是针对只包含音频的视频格式,比如音频的 mp4,仅 H5 支持。 |
|
|
||||||
| qualitySort | String | 指定排序方式,只有使用 vid + plauth 播放方式时支持。‘desc’表示按倒序排序(即:从大到小排序),‘asc’表示按正序排序(即:从小到大排序),默认值:‘asc’,仅 H5 支持。 |
|
|
||||||
| definition | String | 显示视频清晰度,多个用逗号分隔,比如:’FD,LD’,此值是 vid 对应流清晰度的一个子集,取值范围:FD(流畅)LD(标清)SD(高清)HD(超清)OD(原画)2K(2K)4K(4K),仅 H5 支持。 |
|
|
||||||
| defaultDefinition | String | 默认视频清晰度,此值是 vid 对应流的一个清晰度,取值范围:FD(流畅)LD(标清)SD(高清)HD(超清)OD(原画)2K(2K)4K(4K),仅 H5 支持。 |
|
|
||||||
| x5_type | String | 声明启用同层 H5 播放器,启用时设置的值为‘h5’,详情参见同层播放。 |
|
|
||||||
| x5_fullscreen | Boolean | 声明视频播放时是否进入到 TBS 的全屏模式,默认为 false。当需要把视频做为背景时,设置为 true,详情参见同层播放。 |
|
|
||||||
| x5_video_position | String | 声明视频播在界面上的位置,默认为“center”。可选值为:“top”,“center”,详情参见同层播放。 |
|
|
||||||
| x5_orientation | String | 声明 TBS 播放器支持的方向,可选值:landscape:横屏,portraint:竖屏,详情参见同层播放。 |
|
|
||||||
| x5LandscapeAsFullScreen | String | 声明 TBS 全屏播放是否横屏,默认值为 true。 |
|
|
||||||
| autoPlayDelay | Number | 延迟播放时间,单位为秒。详情参见延迟播放 |
|
|
||||||
| autoPlayDelayDisplayText | String | 延迟播放提示文本,详情参见延迟播放。 |
|
|
||||||
| language | String | 国际化,默认为‘zh-cn’。如果未设置,则采用浏览器语言。可选值为‘zh-cn’、‘en-us’或其它值。 |
|
|
||||||
| languageTexts | JSON | 自定义国际化文本 json 结构,key 的值需要和 language 属性值对应起来。例子:{jp:{Play:”Play”}},自定义值参见 Json 结构。 |
|
|
||||||
| snapshot | Boolean | flash 启用截图功能。 |
|
|
||||||
| snapshotWatermark | Object | H5 设置截图水印。 |
|
|
||||||
| useHlsPluginForSafari | Boolean | Safari 浏览器可以启用 Hls 插件播放,Safari 11 除外。 |
|
|
||||||
| enableStashBufferForFlv | Boolean | H5 播放 flv 时,设置是否启用播放缓存,只在直播下起作用。 |
|
|
||||||
| stashInitialSizeForFlv | Number | H5 播放 flv 时,初始缓存大小,只在直播下起作用。 |
|
|
||||||
| loadDataTimeout | Number | 缓冲多长时间后,提示用户切换低清晰度,默认:20 秒。 |
|
|
||||||
| waitingTimeout | Number | 最大缓冲超时时间,超过这个时间会有错误提示,默认:60 秒。 |
|
|
||||||
| liveStartTime | String | 直播开始时间,直播时移功能使用,格式为:“2018/01/04 12:00:00”。 |
|
|
||||||
| liveOverTime | String | 直播结束时间,直播时移功能使用,格式为:“2018/01/04 12:00:00”。 |
|
|
||||||
| liveTimeShiftUrl | String | 直播可用时移查询地址,详情参见直播时移。 |
|
|
||||||
| liveShiftSource | String | flv 直播地址播放时,hls 的流地址,详情参见直播时移。 |
|
|
||||||
| recreatePlayer | Function | flv 直播和 hls 时移切换是,重新创建播放器方法,详情参见直播时移。 |
|
|
||||||
| diagnosisButtonVisible | Boolean | 是否显示检测按钮,默认为 true。 |
|
|
||||||
| disableSeek | Boolean | 禁用进度条的 Seek,默认为 false,仅 Flash 支持。 |
|
|
||||||
| encryptType | int | 加密类型,播放点播私有加密视频时,设置值为 1,默认值为 0。 |
|
|
||||||
| progressMarkers | Array | 进度条打点内容数组,详情参见进度条打点。 |
|
|
||||||
| vodRetry | int | 点播失败重试次数,默认 3 次 |
|
|
||||||
| liveRetry | int | 直播播放失败重试次数,默认 5 次 |
|
|
||||||
|
|
||||||
### 3.2 播放器方法
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 暂停播放
|
|
||||||
this.$refs.VueAliplayerV2.pause();
|
|
||||||
```
|
|
||||||
|
|
||||||
可以参考 [播放器接口方法](https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.6.1085.36fc6fc57WKZ5P#h2-u64ADu653Eu5668u63A5u53E32)
|
|
||||||
|
|
||||||
| 名称 | 参数 | 说明 |
|
|
||||||
| :--------------------- | :------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| play | - | 播放视频。 |
|
|
||||||
| pause | - | 暂停视频。 |
|
|
||||||
| replay | - | 重播视频。 |
|
|
||||||
| seek | time | 跳转到某个时刻进行播放,time 的单位为秒。 |
|
|
||||||
| getCurrentTime | - | 获取当前的播放时刻,返回的单位为秒。 |
|
|
||||||
| getDuration | - | 获取视频总时长,返回的单位为秒,这个需要在视频加载完成以后才可以获取到,可以在 play 事件后获取。 |
|
|
||||||
| getVolume | - | 获取当前的音量,返回值为 0-1 的实数。ios 和部分 android 会失效。 |
|
|
||||||
| setVolume | - | 设置音量,vol 为 0-1 的实数,ios 和部分 android 会失效。 |
|
|
||||||
| loadByUrl | url,time | 直接播放视频 url,time 为可选值(单位秒)。目前只支持同种格式(mp4/flv/m3u8)之间切换。暂不支持直播 rtmp 流切换。 |
|
|
||||||
| replayByVidAndPlayAuth | vid:视频 id,playauth:播放凭证 | 目前只支持 H5 播放器。暂不支持不同格式视频间的之间切换。暂不支持直播 rtmp 流切换。 |
|
|
||||||
| replayByVidAndAuthInfo | 仅 MPS 用户时使用,参数顺序为:vid、accId、accSecret、stsToken、authInfo、domainRegion | 目前只支持 H5 播放器。暂不支持不同格式视频间的之间切换。暂不支持直播 rtmp 流切换。 |
|
|
||||||
| setPlayerSize | w,h | 设置播放器大小 w,h 可分别为 400px 像素或 60%百分比。chrome 浏览器下 flash 播放器分别不能小于 397x297。 |
|
|
||||||
| setSpeed | speed | 手动设置播放的倍速,倍速播放仅 H5 支持。移动端可能会失效,比如 android 微信。倍速播放 UI 默认是开启的。如果自定义过 skinLaout 属性,需要添加 speedButton 项到数组里: |
|
|
||||||
| > | > | {name:“speedButton”,align:“tr”,x:10,y:23} |
|
|
||||||
| setSanpshotProperties | width:宽度,height:高度,rate:截图质量 | 设置截图参数。 |
|
|
||||||
| requestFullScreen | - | 播放器全屏,仅 H5 支持。 |
|
|
||||||
| cancelFullScreen | - | 播放器退出全屏,iOS 调用无效,仅 H5 支持。 |
|
|
||||||
| getIsFullScreen | - | 获取播放器全屏状态,仅 H5 支持。 |
|
|
||||||
| getStatus | - | 获取播放器状态,包含的值:‘init’,‘ready’,‘loading’,‘play’,‘pause’,‘playing’,‘waiting’,‘error’,‘ended’ |
|
|
||||||
| setLiveTimeRange | 开始时间,结束时间 | 设置直播的开始结束时间,开启直播时移功能时使用。例子:player.liveShiftSerivce.setLiveTimeRange(“”,‘2018/01/04 20:00:00’) |
|
|
||||||
| setRotate | rotate 旋转角度 | 参数为旋转角度, 正数为正时针旋转, 负数为逆时针旋转。例如: setRotate(90)。详情参见旋转和镜像。 |
|
|
||||||
| getRotate | - | 获取旋转角度。详情参见旋转和镜像。 |
|
|
||||||
| setImage | image:镜像类型,可选值为:horizon,vertical | 设置镜像,例如: setImage(‘horizon’)。详情参见旋转和镜像。 |
|
|
||||||
| dispose | - | 播放器销毁 |
|
|
||||||
| setCover | cover 封面地址 | 设置封面 |
|
|
||||||
| setProgressMarkers | markers 打点数据集合 | 设置打点数据 |
|
|
||||||
| setPreviewTime | time 试看时间 | 设置试看时间,单位为秒,详情参见试看 |
|
|
||||||
| getPreviewTime | - | 获取试看时间 |
|
|
||||||
| isPreview | - | 是否试看 |
|
|
||||||
| off | ev:事件名[String],handle,事件回调方法[Function] | 通过播放器实例的 off 方法取消绑定的方法 |
|
|
||||||
|
|
||||||
## 4.播放器事件
|
|
||||||
|
|
||||||
```html
|
|
||||||
<template>
|
|
||||||
<vue-aliplayer-v2 @ready="handleReady" />
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* 播放器事件回调
|
|
||||||
*/
|
|
||||||
handleReady(e) {
|
|
||||||
console.log(`ready`, e);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
可以参考 [播放器事件](https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.6.1085.36fc6fc57WKZ5P#h2-u64ADu653Eu5668u4E8Bu4EF63)
|
## Props
|
||||||
|
|
||||||
| 名称 | 说明 |
|
| 名称 | 类型 | 默认值 | 说明 |
|
||||||
| :---------------- | :--------------------------------------------------------------------------------------------------------------------------------------- |
|
| --- | --- | --- | --- |
|
||||||
| ready | 播放器视频初始化按钮渲染完毕。播放器 UI 初始设置需要此事件后触发,避免 UI 被初始化所覆盖。播放器提供的方法需要在此事件发生后才可以调用。 |
|
| `source` | `string \| null` | `null` | 播放源。存在时优先于 `options.source`,变更后会调用底层 `loadByUrl` 动态切换。 |
|
||||||
| play | 视频由暂停恢复为播放时触发。 |
|
| `options` | `AliplayerOptions \| null` | `null` | 透传给 Aliplayer 的配置项。 |
|
||||||
| pause | 视频暂停时触发。 |
|
| `license` | `AliplayerLicense \| null` | `null` | Aliplayer License 配置,等价于 `options.license`,适配新版 SDK 要求。 |
|
||||||
| canplay | 能够开始播放音频/视频时发生,会多次触发,仅 H5 播放器。 |
|
| `autoFormat` | `boolean` | `true` | 根据 `source` 后缀自动补充 `format`,支持 `mp4/m3u8/flv/mp3/rtmp`。 |
|
||||||
| playing | 播放中,会触发多次。 |
|
| `lowLatency` | `boolean` | `false` | FLV 直播低延迟预设,会在 `isLive + flv` 时默认关闭 stash buffer。 |
|
||||||
| ended | 当前视频播放完毕时触发。 |
|
| `normalizeSourceUrl` | `boolean` | `true` | 自动对非 ASCII 播放地址执行 `encodeURI`,处理中文文件名等 URL。 |
|
||||||
| liveStreamStop | 直播流中断时触发。m3u8/flv/rtmp 在重试 5 次未成功后触发。提示上层流中断或需要重新加载视频。PS:m3u8 一直自动重试,不需要上层添加重试。 |
|
| `forbidFastForward` | `boolean` | `false` | 禁止拖拽快进。通过监听 `timeupdate` 回退到上次播放位置实现。 |
|
||||||
| onM3u8Retry | m3u8 直播流中断后重试事件,每次断流只触发一次。 |
|
| `sdkVersion` | `string` | `2.37.0` | 生成阿里云 `imp-web-player` SDK 资源地址。 |
|
||||||
| hideBar | 控制栏自动隐藏事件。 |
|
| `cssLink` | `string` | Aliplayer 2.37.0 CSS | 覆盖播放器样式地址。 |
|
||||||
| showBar | 控制栏自动显示事件。 |
|
| `scriptSrc` | `string` | Aliplayer 2.37.0 JS | 覆盖播放器脚本地址。 |
|
||||||
| waiting | 数据缓冲事件。 |
|
| `componentScripts` | `string[]` | `[]` | 额外加载自定义组件脚本,需在播放器初始化前加载。 |
|
||||||
| timeupdate | 播放位置发生改变时触发,仅 H5 播放器。可通过 getCurrentTime 方法,得到当前播放时间。 |
|
| `disableTracking` | `boolean` | `false` | 可选拦截 Aliplayer 已知 track 上报请求。 |
|
||||||
| snapshoted | 截图完成事件。 |
|
| `trackingUrlPatterns` | `Array<string \| RegExp>` | `[]` | 自定义需要拦截的 track URL 片段或正则。 |
|
||||||
| requestFullScreen | 全屏事件,仅 H5 支持。 |
|
|
||||||
| cancelFullScreen | 取消全屏事件,iOS 下不会触发,仅 H5 支持。 |
|
|
||||||
| error | 错误事件。 |
|
|
||||||
| startSeek | 开始拖拽,参数返回拖拽点的时间。 |
|
|
||||||
| completeSeek | 完成拖拽,参数返回拖拽点的时间。 |
|
|
||||||
|
|
||||||
---
|
## Events
|
||||||
|
|
||||||
## 5. 图片展示
|
组件会透传常用 Aliplayer 事件:
|
||||||
|
|
||||||

|
```ts
|
||||||

|
ready
|
||||||
|
play
|
||||||
---
|
pause
|
||||||
|
canplay
|
||||||
## 6.二次开发 下载项目
|
playing
|
||||||
|
ended
|
||||||
```bash
|
liveStreamStop
|
||||||
git clone https://github.com/langyuxiansheng/vue-aliplayer-v2.git
|
onM3u8Retry
|
||||||
|
hideBar
|
||||||
|
showBar
|
||||||
|
waiting
|
||||||
|
timeupdate
|
||||||
|
snapshoted
|
||||||
|
requestFullScreen
|
||||||
|
cancelFullScreen
|
||||||
|
error
|
||||||
|
startSeek
|
||||||
|
completeSeek
|
||||||
|
sdk-error
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project setup
|
`sdk-error` 是组件额外事件,在 Aliplayer SDK 脚本加载失败时触发。
|
||||||
|
|
||||||
|
## Ref 方法
|
||||||
|
|
||||||
|
```ts
|
||||||
|
playerRef.value?.play();
|
||||||
|
playerRef.value?.pause();
|
||||||
|
playerRef.value?.replay();
|
||||||
|
playerRef.value?.seek(30);
|
||||||
|
playerRef.value?.getCurrentTime();
|
||||||
|
playerRef.value?.getDuration();
|
||||||
|
playerRef.value?.getVolume();
|
||||||
|
playerRef.value?.setVolume(0.8);
|
||||||
|
playerRef.value?.loadByUrl('//player.alicdn.com/video/aliyunmedia.mp4');
|
||||||
|
playerRef.value?.getStatus();
|
||||||
|
playerRef.value?.requestFullScreen();
|
||||||
|
playerRef.value?.cancelFullScreen();
|
||||||
|
playerRef.value?.dispose();
|
||||||
|
playerRef.value?.getPlayer();
|
||||||
|
```
|
||||||
|
|
||||||
|
完整暴露方法包括:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
getPlayer
|
||||||
|
init
|
||||||
|
initPlayer
|
||||||
|
reload
|
||||||
|
retry
|
||||||
|
play
|
||||||
|
pause
|
||||||
|
replay
|
||||||
|
seek
|
||||||
|
getCurrentTime
|
||||||
|
getDuration
|
||||||
|
getVolume
|
||||||
|
setVolume
|
||||||
|
loadByUrl
|
||||||
|
replayByVidAndPlayAuth
|
||||||
|
replayByVidAndAuthInfo
|
||||||
|
setPlayerSize
|
||||||
|
setSpeed
|
||||||
|
setSanpshotProperties
|
||||||
|
requestFullScreen
|
||||||
|
cancelFullScreen
|
||||||
|
getIsFullScreen
|
||||||
|
getStatus
|
||||||
|
setLiveTimeRange
|
||||||
|
setRotate
|
||||||
|
getRotate
|
||||||
|
setImage
|
||||||
|
dispose
|
||||||
|
setCover
|
||||||
|
setProgressMarkers
|
||||||
|
setPreviewTime
|
||||||
|
getPreviewTime
|
||||||
|
isPreview
|
||||||
|
off
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多播放器
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<VueAliplayerV2
|
||||||
|
v-for="item in sources"
|
||||||
|
:key="item"
|
||||||
|
:source="item"
|
||||||
|
:options="options"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
v2 的 SDK 加载器会复用同一份 CSS/JS 资源,多个播放器同时挂载时不会重复插入相同的 SDK 标签。
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
阿里云新版 Web 播放器 SDK 要求配置网站域名和 License Key。可以通过 `license` prop 或 `options.license` 传入:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<VueAliplayerV2
|
||||||
|
:source="source"
|
||||||
|
:license="{ domain: 'example.com', key: 'example-key' }"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## VID + PlayAuth
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<VueAliplayerV2
|
||||||
|
:options="{
|
||||||
|
vid: '<your video ID>',
|
||||||
|
playauth: '<your PlayAuth>',
|
||||||
|
authTimeout: 7200
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
`vid + playauth` 是初始化配置,不需要再传 `source`。如果要在播放器创建后切换,可以调用:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
playerRef.value?.replayByVidAndPlayAuth(vid, playauth);
|
||||||
|
```
|
||||||
|
|
||||||
|
## FLV/HLS/RTMP 说明
|
||||||
|
|
||||||
|
- FLV 直播请设置 `options.isLive = true`,组件会自动推断 `format: 'flv'`。
|
||||||
|
- 开启 `low-latency` 后,FLV 直播默认使用 `enableStashBufferForFlv: false` 和 `stashInitialSizeForFlv: 128`,可在 `options` 中覆盖。
|
||||||
|
- m3u8、flv、mp4 跨格式切换时,v2 会自动重建播放器;同格式切换优先调用 `loadByUrl`。
|
||||||
|
- RTMP 在现代浏览器 H5 模式下不再可靠,建议服务端转 HLS/FLV/RTS。
|
||||||
|
|
||||||
|
## 自定义组件和跑马灯
|
||||||
|
|
||||||
|
Aliplayer 自定义组件需要额外加载组件脚本,然后通过 `options.components` 注入。组件提供 `componentScripts` 保证脚本在播放器初始化前加载:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<VueAliplayerV2
|
||||||
|
:source="source"
|
||||||
|
:component-scripts="['/aliplayer-components/playlist.js']"
|
||||||
|
:options="{
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'PlaylistComponent',
|
||||||
|
type: window.PlaylistComponent,
|
||||||
|
args: { list: playlist }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
跑马灯、水印、播放列表等能力是否可用取决于所加载的 Aliplayer 自定义组件脚本。
|
||||||
|
|
||||||
|
## 失败重试
|
||||||
|
|
||||||
|
播放器错误页属于 Aliplayer SDK 内部 UI。业务侧可以监听 `error` 后使用组件暴露的 `retry()` 或 `reload()` 做局部重试:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
function handleError() {
|
||||||
|
playerRef.value?.retry();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd vue-aliplayer-v2
|
|
||||||
|
|
||||||
npm install
|
npm install
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compiles and minifies for production
|
构建 demo:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Lints and fixes files
|
构建组件库:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run lint
|
npm run type-check
|
||||||
|
npm run lib
|
||||||
```
|
```
|
||||||
|
|
||||||
## 7.缺陷 & 后期计划
|
## 迁移说明
|
||||||
|
|
||||||
> 2019 年 12 月 27 日 更新优化局部引用方式
|
- v2 仅支持 Vue 3。
|
||||||
|
- 入口从 Vue 2 插件模式迁移为 Vue 3 `app.use(...)`。
|
||||||
> 您有功能建议,或者 bug 反馈请留言.
|
- 组件 ref 需要通过 `ref<VueAliplayerV2Expose | null>` 使用。
|
||||||
|
- 旧版本用户请安装 `vue-aliplayer-v2@1.x`。
|
||||||
## 8.感谢
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
- vue-aliplayer 的作者,项目地址:https://github.com/slacrey/vue-aliplayer
|
|
||||||
|
|
||||||
- Alipayer 阿里云的开源播放器 https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.6.1085.36fc6fc57WKZ5P#h2-u64ADu653Eu5668u4E8Bu4EF63
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
||||||
|
|
||||||
## 更新日志
|
|
||||||
|
|
||||||
> v1.3.0 修复部分已知bug,增加forbidFastForward 属性,感谢 "william-xue"网友的功能提交.
|
|
||||||
|
|
||||||
- sdk 版本更新,默认 SDK 版本由 2.9.3 更新为 2.9.20
|
|
||||||
- 默认注释更新
|
|
||||||
- 增加禁止用户拖拽快进的属性选项 forbidFastForward [Boolean] 默认 false
|
|
||||||
|
|
||||||
> v1.2.9 修正部分默认属性, 感谢"Schean17"网友的反馈与建议.
|
|
||||||
|
|
||||||
> v1.2.8 更换底层默认 sdk 版本为 2.9.3 修复 options 遇到 update loop 错误 感谢"litmonw"网友的反馈与建议.
|
|
||||||
|
|
||||||
> v1.2.7 更换底层默认 sdk 版本为 2.9.1 的版本. 更新线上演示 demo 的选项
|
|
||||||
|
|
||||||
> v1.2.6 优化 beforeDestroy() 部分的代码.
|
|
||||||
|
|
||||||
> v1.2.5 更换默认的播放器 SDK 版本 2.8.2 => 2.9.0,2.8.2 的版本存在多个播放器同时播放直播流异常的 bug,增加了全局 SDK 版本配置,可以在 Vue.use()的时候进行配置.
|
|
||||||
|
|
||||||
> v1.2.4 修复多个播放器加载,只初始化一个播放器的 bug.文档部分更新,增加了问题栏. 感谢"沙洲 ad"的反馈与建议.
|
|
||||||
|
|
||||||
> v1.2.3 优化播放器的初始化代码,调整包内结构,优化局部组件的注册方式,也兼容老版本的引用方式.文档部分更新,增加了问题栏. 感谢"liangzhiyuan2015"和"fancheur"两位网友的反馈与建议.
|
|
||||||
|
|
||||||
> v1.2.2 修复指定 id 情况下,播放器报错"没有为播放器指定容器",目前移除外部指定 id 的方式,所有的播放器 id 都由内部生成,不再由外部指定容器(外部指定的意义并不大),其它的说明:更新 1.2.1 后报错 Uncaught TypeError: 没有为播放器指定容器,因为源码中变更了部分代码,以及最大限度的简化代码,组件内部的根容器就只有一个 div 容器,导致以前外部指定 id 的时候,容器 id 与外部的不一致,导致抛出异常了,现在已经紧急修复了,若在使用,请更新到 v1.2.2 的版本;如果使用了外部指定 id 的方式请移除外部的 id.否则 id 会出现重复的情况., 感谢"liyoro"的反馈和建议.
|
|
||||||
|
|
||||||
> v1.2.1 修复直播播放的情况下,播放器已经销毁,而后台还在继续下载资源造成卡顿的 bug,修复多个播放器只渲染 1 个的 bug, 感谢"Jonauil"和"guangming95"两位网友的反馈和建议.
|
|
||||||
|
|
||||||
> v1.2.0 修复播放源(MP4/m3u8)之间切换无法正常播放的 bug,增加 options 配置项动态响应功能,优化部分播放器的逻辑, 感谢"liyoro"网友的反馈和建议.
|
|
||||||
|
|
||||||
> v1.1.9 修复播放源(修复 prop:source 类型验证报错), 感谢"hugo2017"和“nullF”网友的反馈.
|
|
||||||
|
|
||||||
> v1.1.8 修复播放源(增加 source 属性类型错误),修复获取播放器状态 getStatus()方法报错, 感谢"kongjigu"网友的反馈.
|
|
||||||
|
|
||||||
> v1.1.7 增加动态切换播放源(增加 source 属性)功能 感谢"wikimo"和"jieruian"两位网友的反馈建议.
|
|
||||||
|
|
||||||
> v1.1.6 修复部分已知 bug 和优化局部的引用方式
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 其它问题
|
|
||||||
|
|
||||||
1. IOS 或者其它设备无法全屏播放,或者点击全屏按钮的时候也只是显示竖屏?
|
|
||||||
|
|
||||||
> 方案与问题所在:
|
|
||||||
|
|
||||||
一般情况下可能是开启了强制竖屏(也就是屏幕锁定)打开后就会竖屏而不会全屏了!如下关闭就可以了:
|
|
||||||
参考 issues: https://github.com/langyuxiansheng/vue-aliplayer-v2/issues/25
|
|
||||||
|
|
||||||
-开启了屏幕锁定,只要上拉控制中心,点击屏幕锁定关闭就可以了!
|
|
||||||
|
|
||||||
-也可能是播放器或者浏览器兼容性问题.
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
'@vue/app'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
1
dist/assets/index-BwNqcy-4.css
vendored
Normal file
1
dist/assets/index-BwNqcy-4.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
dist/assets/index-Cx06WFub.js
vendored
Normal file
6
dist/assets/index-Cx06WFub.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/css/index.06951331.css
vendored
1
dist/css/index.06951331.css
vendored
@ -1 +0,0 @@
|
|||||||
[data-v-9b14a31e]{margin:0;padding:0}.remove-text[data-v-9b14a31e]{text-align:center;padding:20px;font-size:24px}.player-btns[data-v-9b14a31e]{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-wrap:wrap;flex-wrap:wrap}.player-btns span[data-v-9b14a31e]{margin:0 auto;display:inline-block;padding:5px 10px;width:150px;height:40px;line-height:40px;border:1px solid #eee;background:#e1e1e1;border-radius:10px;text-align:center;margin:20px auto;cursor:pointer}
|
|
||||||
15
dist/index.html
vendored
15
dist/index.html
vendored
@ -1 +1,14 @@
|
|||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/vue-aliplayer-v2/favicon.ico><title>vue-aliplayer-v2</title><link href=/vue-aliplayer-v2/css/index.06951331.css rel=preload as=style><link href=/vue-aliplayer-v2/js/chunk-vendors.69bad5f4.js rel=preload as=script><link href=/vue-aliplayer-v2/js/index.b7f22f1a.js rel=preload as=script><link href=/vue-aliplayer-v2/css/index.06951331.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue-aliplayer-v2 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/vue-aliplayer-v2/js/chunk-vendors.69bad5f4.js></script><script src=/vue-aliplayer-v2/js/index.b7f22f1a.js></script></body></html>
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="icon" href="/vue-aliplayer-v2/favicon.ico">
|
||||||
|
<title>vue-aliplayer-v2</title>
|
||||||
|
<script type="module" crossorigin src="/vue-aliplayer-v2/assets/index-Cx06WFub.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/vue-aliplayer-v2/assets/index-BwNqcy-4.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
8
dist/js/chunk-vendors.69bad5f4.js
vendored
8
dist/js/chunk-vendors.69bad5f4.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/index.b7f22f1a.js
vendored
2
dist/js/index.b7f22f1a.js
vendored
File diff suppressed because one or more lines are too long
8
env.d.ts
vendored
Normal file
8
env.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue';
|
||||||
|
|
||||||
|
const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
|
||||||
|
export default component;
|
||||||
|
}
|
||||||
1413
examples/App.vue
1413
examples/App.vue
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
import App from './App.vue';
|
|
||||||
import VueAliplayerV2 from '../packages';
|
|
||||||
Vue.use(VueAliplayerV2,{
|
|
||||||
// cssLink: 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css',
|
|
||||||
// scriptSrc: 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'
|
|
||||||
});
|
|
||||||
Vue.config.productionTip = false;
|
|
||||||
new Vue({
|
|
||||||
render: h => h(App),
|
|
||||||
}).$mount('#app');
|
|
||||||
4
examples/main.ts
Normal file
4
examples/main.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
|
||||||
|
createApp(App).mount('#app');
|
||||||
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="icon" href="/favicon.ico">
|
||||||
|
<title>vue-aliplayer-v2</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/examples/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,10 +0,0 @@
|
|||||||
<meta charset="utf-8">
|
|
||||||
<title>vue-aliplayer-v2 demo</title>
|
|
||||||
<script src="./vue-aliplayer-v2.umd.js"></script>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="./vue-aliplayer-v2.css">
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
console.log(vue-aliplayer-v2)
|
|
||||||
</script>
|
|
||||||
59
lib/types/AliplayerV2/index.vue.d.ts
vendored
Normal file
59
lib/types/AliplayerV2/index.vue.d.ts
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import type { AliplayerOptions, AliplayerV2Props, VueAliplayerV2Expose } from './types';
|
||||||
|
declare const __VLS_export: import("vue").DefineComponent<AliplayerV2Props, VueAliplayerV2Expose, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
||||||
|
canplay: (payload?: unknown) => any;
|
||||||
|
ended: (payload?: unknown) => any;
|
||||||
|
error: (payload?: unknown) => any;
|
||||||
|
pause: (payload?: unknown) => any;
|
||||||
|
play: (payload?: unknown) => any;
|
||||||
|
playing: (payload?: unknown) => any;
|
||||||
|
timeupdate: (payload?: unknown) => any;
|
||||||
|
waiting: (payload?: unknown) => any;
|
||||||
|
ready: (payload?: unknown) => any;
|
||||||
|
liveStreamStop: (payload?: unknown) => any;
|
||||||
|
onM3u8Retry: (payload?: unknown) => any;
|
||||||
|
hideBar: (payload?: unknown) => any;
|
||||||
|
showBar: (payload?: unknown) => any;
|
||||||
|
snapshoted: (payload?: unknown) => any;
|
||||||
|
requestFullScreen: (payload?: unknown) => any;
|
||||||
|
cancelFullScreen: (payload?: unknown) => any;
|
||||||
|
startSeek: (payload?: unknown) => any;
|
||||||
|
completeSeek: (payload?: unknown) => any;
|
||||||
|
"sdk-error": (error: Error) => any;
|
||||||
|
}, string, import("vue").PublicProps, Readonly<AliplayerV2Props> & Readonly<{
|
||||||
|
onCanplay?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onEnded?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onError?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onPause?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onPlay?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onPlaying?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onTimeupdate?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onWaiting?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onReady?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onLiveStreamStop?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onOnM3u8Retry?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onHideBar?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onShowBar?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onSnapshoted?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onRequestFullScreen?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onCancelFullScreen?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onStartSeek?: ((payload?: unknown) => any) | undefined;
|
||||||
|
onCompleteSeek?: ((payload?: unknown) => any) | undefined;
|
||||||
|
"onSdk-error"?: ((error: Error) => any) | undefined;
|
||||||
|
}>, {
|
||||||
|
source: string | null;
|
||||||
|
autoFormat: boolean;
|
||||||
|
forbidFastForward: boolean;
|
||||||
|
license: import("./types").AliplayerLicense | null;
|
||||||
|
lowLatency: boolean;
|
||||||
|
normalizeSourceUrl: boolean;
|
||||||
|
options: AliplayerOptions | null;
|
||||||
|
sdkVersion: string;
|
||||||
|
cssLink: string;
|
||||||
|
scriptSrc: string;
|
||||||
|
componentScripts: string[];
|
||||||
|
disableTracking: boolean;
|
||||||
|
trackingUrlPatterns: Array<string | RegExp>;
|
||||||
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
||||||
|
declare const _default: typeof __VLS_export;
|
||||||
|
export default _default;
|
||||||
|
//# sourceMappingURL=index.vue.d.ts.map
|
||||||
12
lib/types/AliplayerV2/sdkLoader.d.ts
vendored
Normal file
12
lib/types/AliplayerV2/sdkLoader.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export declare const DEFAULT_SDK_VERSION = "2.37.0";
|
||||||
|
export declare const DEFAULT_CSS_LINK = "https://g.alicdn.com/apsara-media-box/imp-web-player/2.37.0/skins/default/aliplayer-min.css";
|
||||||
|
export declare const DEFAULT_SCRIPT_SRC = "https://g.alicdn.com/apsara-media-box/imp-web-player/2.37.0/aliplayer-min.js";
|
||||||
|
export declare function getCssLinkByVersion(version: string): string;
|
||||||
|
export declare function getScriptSrcByVersion(version: string): string;
|
||||||
|
/**
|
||||||
|
* Shared SDK loader. It prevents duplicate CSS/JS tags when several player
|
||||||
|
* instances mount at the same time or are recreated by route changes.
|
||||||
|
*/
|
||||||
|
export declare function loadAliplayerSdk(cssLink: string, scriptSrc: string): Promise<void>;
|
||||||
|
export declare function loadExtraScripts(scriptUrls?: string[]): Promise<void>;
|
||||||
|
//# sourceMappingURL=sdkLoader.d.ts.map
|
||||||
4
lib/types/AliplayerV2/source.d.ts
vendored
Normal file
4
lib/types/AliplayerV2/source.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export type SourceFormat = 'mp4' | 'm3u8' | 'flv' | 'rtmp' | 'mp3' | null;
|
||||||
|
export declare function inferSourceFormat(source?: string | null): SourceFormat;
|
||||||
|
export declare function normalizeSource(source?: string | null): string | null;
|
||||||
|
//# sourceMappingURL=source.d.ts.map
|
||||||
7
lib/types/AliplayerV2/tracking.d.ts
vendored
Normal file
7
lib/types/AliplayerV2/tracking.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export declare function installTrackingBlocker(patterns?: Array<string | RegExp>): void;
|
||||||
|
declare global {
|
||||||
|
interface XMLHttpRequest {
|
||||||
|
__vueAliplayerV2Blocked?: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=tracking.d.ts.map
|
||||||
128
lib/types/AliplayerV2/types.d.ts
vendored
Normal file
128
lib/types/AliplayerV2/types.d.ts
vendored
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import type { Plugin } from 'vue';
|
||||||
|
export interface VueAliplayerV2Options {
|
||||||
|
sdkVersion?: string;
|
||||||
|
cssLink?: string;
|
||||||
|
scriptSrc?: string;
|
||||||
|
componentScripts?: string[];
|
||||||
|
disableTracking?: boolean;
|
||||||
|
trackingUrlPatterns?: Array<string | RegExp>;
|
||||||
|
}
|
||||||
|
export interface AliplayerV2Props extends VueAliplayerV2Options {
|
||||||
|
autoFormat?: boolean;
|
||||||
|
forbidFastForward?: boolean;
|
||||||
|
license?: AliplayerLicense | null;
|
||||||
|
lowLatency?: boolean;
|
||||||
|
normalizeSourceUrl?: boolean;
|
||||||
|
options?: AliplayerOptions | null;
|
||||||
|
source?: string | null;
|
||||||
|
}
|
||||||
|
export interface AliplayerLicense {
|
||||||
|
domain: string;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
export type AliplayerEventName = 'ready' | 'play' | 'pause' | 'canplay' | 'playing' | 'ended' | 'liveStreamStop' | 'onM3u8Retry' | 'hideBar' | 'showBar' | 'waiting' | 'timeupdate' | 'snapshoted' | 'requestFullScreen' | 'cancelFullScreen' | 'error' | 'startSeek' | 'completeSeek';
|
||||||
|
export interface AliplayerOptions {
|
||||||
|
id?: string;
|
||||||
|
source?: string;
|
||||||
|
width?: string;
|
||||||
|
autoplay?: boolean;
|
||||||
|
isLive?: boolean;
|
||||||
|
format?: string;
|
||||||
|
license?: AliplayerLicense;
|
||||||
|
vid?: string;
|
||||||
|
playauth?: string;
|
||||||
|
accessKeyId?: string;
|
||||||
|
securityToken?: string;
|
||||||
|
accessKeySecret?: string;
|
||||||
|
region?: string;
|
||||||
|
authTimeout?: number;
|
||||||
|
components?: unknown[];
|
||||||
|
enableStashBufferForFlv?: boolean;
|
||||||
|
stashInitialSizeForFlv?: number;
|
||||||
|
rtsVersion?: string;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface AliplayerFullscreenService {
|
||||||
|
requestFullScreen: () => void;
|
||||||
|
cancelFullScreen: () => void;
|
||||||
|
getIsFullScreen: () => boolean;
|
||||||
|
}
|
||||||
|
export interface AliplayerLiveShiftService {
|
||||||
|
setLiveTimeRange: (beginTime: string, endTime: string) => void;
|
||||||
|
}
|
||||||
|
export interface AliplayerInstance {
|
||||||
|
on: (eventName: string, handler: (event?: unknown) => void) => void;
|
||||||
|
off?: (eventName: string, handler: (event?: unknown) => void) => void;
|
||||||
|
play: () => void;
|
||||||
|
pause: () => void;
|
||||||
|
replay: () => void;
|
||||||
|
seek: (time: number) => void;
|
||||||
|
getCurrentTime: () => number;
|
||||||
|
getDuration: () => number;
|
||||||
|
getVolume: () => number;
|
||||||
|
setVolume: (volume: number) => void;
|
||||||
|
loadByUrl: (url: string, time?: number) => void;
|
||||||
|
replayByVidAndPlayAuth: (vid: string, playauth: string) => void;
|
||||||
|
replayByVidAndAuthInfo: (vid: string, accId: string, accSecret: string, stsToken: string, authInfo: string, domainRegion: string) => void;
|
||||||
|
setPlayerSize: (width: string, height: string) => void;
|
||||||
|
setSpeed: (speed: number) => void;
|
||||||
|
setSanpshotProperties: (width: number, height: number, rate: number) => void;
|
||||||
|
fullscreenService?: AliplayerFullscreenService;
|
||||||
|
getStatus: () => string;
|
||||||
|
liveShiftSerivce?: AliplayerLiveShiftService;
|
||||||
|
setRotate: (rotate: number) => void;
|
||||||
|
getRotate: () => number;
|
||||||
|
setImage: (image: string) => void;
|
||||||
|
dispose: () => void;
|
||||||
|
setCover: (cover: string) => void;
|
||||||
|
setProgressMarkers: (markers: unknown[]) => void;
|
||||||
|
setPreviewTime: (time: number) => void;
|
||||||
|
getPreviewTime: () => number;
|
||||||
|
isPreview: () => boolean;
|
||||||
|
}
|
||||||
|
export interface VueAliplayerV2Expose {
|
||||||
|
getPlayer: () => AliplayerInstance | null;
|
||||||
|
init: () => Promise<void>;
|
||||||
|
initPlayer: () => void;
|
||||||
|
reload: (nextSource?: string) => Promise<void>;
|
||||||
|
retry: (nextSource?: string) => Promise<void>;
|
||||||
|
play: () => void;
|
||||||
|
pause: () => void;
|
||||||
|
replay: () => void;
|
||||||
|
seek: (time: number) => void;
|
||||||
|
getCurrentTime: () => number | undefined;
|
||||||
|
getDuration: () => number | undefined;
|
||||||
|
getVolume: () => number | undefined;
|
||||||
|
setVolume: (volume: number) => void;
|
||||||
|
loadByUrl: (url: string, time?: number) => void;
|
||||||
|
replayByVidAndPlayAuth: (vid: string, playauth: string) => void;
|
||||||
|
replayByVidAndAuthInfo: (vid: string, accId: string, accSecret: string, stsToken: string, authInfo: string, domainRegion: string) => void;
|
||||||
|
setPlayerSize: (width: string, height: string) => void;
|
||||||
|
setSpeed: (speed: number) => void;
|
||||||
|
setSanpshotProperties: (width: number, height: number, rate: number) => void;
|
||||||
|
requestFullScreen: () => void;
|
||||||
|
cancelFullScreen: () => void;
|
||||||
|
getIsFullScreen: () => boolean | undefined;
|
||||||
|
getStatus: () => string | undefined;
|
||||||
|
setLiveTimeRange: (beginTime: string, endTime: string) => void;
|
||||||
|
setRotate: (rotate: number) => void;
|
||||||
|
getRotate: () => number | undefined;
|
||||||
|
setImage: (image: string) => void;
|
||||||
|
dispose: () => void;
|
||||||
|
setCover: (cover: string) => void;
|
||||||
|
setProgressMarkers: (markers: unknown[]) => void;
|
||||||
|
setPreviewTime: (time: number) => void;
|
||||||
|
getPreviewTime: () => number | undefined;
|
||||||
|
isPreview: () => boolean | undefined;
|
||||||
|
off: (eventName: string, handler: (event?: unknown) => void) => void;
|
||||||
|
}
|
||||||
|
export type VueAliplayerV2Plugin = Plugin & {
|
||||||
|
Player?: unknown;
|
||||||
|
};
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
Aliplayer?: (options: AliplayerOptions) => AliplayerInstance;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=types.d.ts.map
|
||||||
32
lib/types/index.d.ts
vendored
Normal file
32
lib/types/index.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import type { App } from 'vue';
|
||||||
|
import VueAliplayerV2 from './AliplayerV2/index.vue';
|
||||||
|
import type { VueAliplayerV2Options } from './AliplayerV2/types';
|
||||||
|
export type { AliplayerEventName, AliplayerInstance, AliplayerLicense, AliplayerOptions, AliplayerV2Props, VueAliplayerV2Expose, VueAliplayerV2Options } from './AliplayerV2/types';
|
||||||
|
type InstallableVueAliplayerV2 = typeof VueAliplayerV2 & {
|
||||||
|
install: (app: App, options?: VueAliplayerV2Options) => void;
|
||||||
|
Player: typeof VueAliplayerV2;
|
||||||
|
props: {
|
||||||
|
sdkVersion: {
|
||||||
|
default: string | (() => string);
|
||||||
|
};
|
||||||
|
cssLink: {
|
||||||
|
default: string | (() => string);
|
||||||
|
};
|
||||||
|
scriptSrc: {
|
||||||
|
default: string | (() => string);
|
||||||
|
};
|
||||||
|
componentScripts: {
|
||||||
|
default: string[] | (() => string[]);
|
||||||
|
};
|
||||||
|
disableTracking: {
|
||||||
|
default: boolean | (() => boolean);
|
||||||
|
};
|
||||||
|
trackingUrlPatterns: {
|
||||||
|
default: Array<string | RegExp> | (() => Array<string | RegExp>);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
declare const installable: InstallableVueAliplayerV2;
|
||||||
|
export { installable as VueAliplayerV2 };
|
||||||
|
export default installable;
|
||||||
|
//# sourceMappingURL=index.d.ts.map
|
||||||
File diff suppressed because it is too large
Load Diff
2
lib/vue-aliplayer-v2.css
Normal file
2
lib/vue-aliplayer-v2.css
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.vue-aliplayer-v2[data-v-cf852d0d]{width:100%}
|
||||||
|
/*$vite$:1*/
|
||||||
395
lib/vue-aliplayer-v2.js
Normal file
395
lib/vue-aliplayer-v2.js
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
import { computed as e, createElementBlock as t, defineComponent as n, nextTick as r, onBeforeUnmount as i, onMounted as a, openBlock as o, ref as s, watch as c } from "vue";
|
||||||
|
//#region packages/AliplayerV2/sdkLoader.ts
|
||||||
|
var l = "2.37.0", u = `https://g.alicdn.com/apsara-media-box/imp-web-player/${l}/skins/default/aliplayer-min.css`, d = `https://g.alicdn.com/apsara-media-box/imp-web-player/${l}/aliplayer-min.js`, f = /* @__PURE__ */ new Map();
|
||||||
|
function p(e) {
|
||||||
|
return `https://g.alicdn.com/apsara-media-box/imp-web-player/${e}/skins/default/aliplayer-min.css`;
|
||||||
|
}
|
||||||
|
function m(e) {
|
||||||
|
return `https://g.alicdn.com/apsara-media-box/imp-web-player/${e}/aliplayer-min.js`;
|
||||||
|
}
|
||||||
|
function h(e) {
|
||||||
|
if (!e || document.querySelector(`link[data-vue-aliplayer-v2-css="${e}"]`)) return;
|
||||||
|
let t = document.createElement("link");
|
||||||
|
t.type = "text/css", t.rel = "stylesheet", t.href = e, t.dataset.vueAliplayerV2Css = e, document.head.appendChild(t);
|
||||||
|
}
|
||||||
|
function g(e, t) {
|
||||||
|
if (!e || t && window[t]) return Promise.resolve();
|
||||||
|
if (f.has(e)) return f.get(e);
|
||||||
|
let n = document.querySelector(`script[data-vue-aliplayer-v2-js="${e}"]`);
|
||||||
|
if (n) {
|
||||||
|
let t = new Promise((t, r) => {
|
||||||
|
if (n.dataset.vueAliplayerV2Loaded === "true") {
|
||||||
|
t();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n.addEventListener("load", () => {
|
||||||
|
n.dataset.vueAliplayerV2Loaded = "true", t();
|
||||||
|
}, { once: !0 }), n.addEventListener("error", () => r(/* @__PURE__ */ Error(`Failed to load Aliplayer SDK: ${e}`)), { once: !0 });
|
||||||
|
});
|
||||||
|
return f.set(e, t), t;
|
||||||
|
}
|
||||||
|
let r = new Promise((t, n) => {
|
||||||
|
let r = document.createElement("script");
|
||||||
|
r.type = "text/javascript", r.src = e, r.dataset.vueAliplayerV2Js = e, r.addEventListener("load", () => {
|
||||||
|
r.dataset.vueAliplayerV2Loaded = "true", t();
|
||||||
|
}, { once: !0 }), r.addEventListener("error", () => n(/* @__PURE__ */ Error(`Failed to load Aliplayer SDK: ${e}`)), { once: !0 }), document.documentElement.appendChild(r);
|
||||||
|
});
|
||||||
|
return f.set(e, r), r;
|
||||||
|
}
|
||||||
|
async function _(e, t) {
|
||||||
|
h(e), await g(t, "Aliplayer");
|
||||||
|
}
|
||||||
|
async function v(e = []) {
|
||||||
|
for (let t of e) await g(t);
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
//#region packages/AliplayerV2/source.ts
|
||||||
|
var y = [
|
||||||
|
"m3u8",
|
||||||
|
"flv",
|
||||||
|
"mp4",
|
||||||
|
"rtmp",
|
||||||
|
"mp3"
|
||||||
|
];
|
||||||
|
function b(e) {
|
||||||
|
if (!e) return null;
|
||||||
|
if (/^rtmps?:\/\//i.test(e)) return "rtmp";
|
||||||
|
let t = e.split("?")[0].split("#")[0].toLowerCase();
|
||||||
|
return y.find((e) => e && t.endsWith(`.${e}`)) || null;
|
||||||
|
}
|
||||||
|
function x(e) {
|
||||||
|
if (!e) return e || null;
|
||||||
|
if (/^(data|blob):/i.test(e)) return e;
|
||||||
|
try {
|
||||||
|
return encodeURI(e);
|
||||||
|
} catch {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
//#region packages/AliplayerV2/tracking.ts
|
||||||
|
var S = ["videocloud.cn-hangzhou.log.aliyuncs.com/logstores/newplayer/track"], C = !1;
|
||||||
|
function w(e, t) {
|
||||||
|
return t.some((t) => typeof t == "string" ? e.includes(t) : t.test(e));
|
||||||
|
}
|
||||||
|
function T(e = S) {
|
||||||
|
if (C) return;
|
||||||
|
C = !0;
|
||||||
|
let t = window.fetch?.bind(window);
|
||||||
|
t && (window.fetch = ((n, r) => w(typeof n == "string" || n instanceof URL ? String(n) : n.url, e) ? Promise.resolve(new Response(null, {
|
||||||
|
status: 204,
|
||||||
|
statusText: "No Content"
|
||||||
|
})) : t(n, r)));
|
||||||
|
let n = XMLHttpRequest.prototype.open, r = XMLHttpRequest.prototype.send;
|
||||||
|
XMLHttpRequest.prototype.open = function(t, r, i, a, o) {
|
||||||
|
this.__vueAliplayerV2Blocked = w(String(r), e), n.call(this, t, r, i ?? !0, a ?? void 0, o ?? void 0);
|
||||||
|
}, XMLHttpRequest.prototype.send = function(e) {
|
||||||
|
this.__vueAliplayerV2Blocked || r.call(this, e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
//#region packages/AliplayerV2/index.vue
|
||||||
|
var E = /* @__PURE__ */ ((e, t) => {
|
||||||
|
let n = e.__vccOpts || e;
|
||||||
|
for (let [e, r] of t) n[e] = r;
|
||||||
|
return n;
|
||||||
|
})(/* @__PURE__ */ n({
|
||||||
|
name: "VueAliplayerV2",
|
||||||
|
__name: "index",
|
||||||
|
props: {
|
||||||
|
autoFormat: {
|
||||||
|
type: Boolean,
|
||||||
|
default: !0
|
||||||
|
},
|
||||||
|
forbidFastForward: {
|
||||||
|
type: Boolean,
|
||||||
|
default: !1
|
||||||
|
},
|
||||||
|
license: { default: null },
|
||||||
|
lowLatency: {
|
||||||
|
type: Boolean,
|
||||||
|
default: !1
|
||||||
|
},
|
||||||
|
normalizeSourceUrl: {
|
||||||
|
type: Boolean,
|
||||||
|
default: !0
|
||||||
|
},
|
||||||
|
options: { default: null },
|
||||||
|
source: { default: null },
|
||||||
|
sdkVersion: { default: l },
|
||||||
|
cssLink: { default: "" },
|
||||||
|
scriptSrc: { default: "" },
|
||||||
|
componentScripts: { default: () => [] },
|
||||||
|
disableTracking: {
|
||||||
|
type: Boolean,
|
||||||
|
default: !1
|
||||||
|
},
|
||||||
|
trackingUrlPatterns: { default: () => [] }
|
||||||
|
},
|
||||||
|
emits: [
|
||||||
|
"ready",
|
||||||
|
"play",
|
||||||
|
"pause",
|
||||||
|
"canplay",
|
||||||
|
"playing",
|
||||||
|
"ended",
|
||||||
|
"liveStreamStop",
|
||||||
|
"onM3u8Retry",
|
||||||
|
"hideBar",
|
||||||
|
"showBar",
|
||||||
|
"waiting",
|
||||||
|
"timeupdate",
|
||||||
|
"snapshoted",
|
||||||
|
"requestFullScreen",
|
||||||
|
"cancelFullScreen",
|
||||||
|
"error",
|
||||||
|
"startSeek",
|
||||||
|
"completeSeek",
|
||||||
|
"sdk-error"
|
||||||
|
],
|
||||||
|
setup(n, { expose: l, emit: f }) {
|
||||||
|
let h = n, g = f, y = s(null), S = s(null), C = s(!1), w = s(null), E = 0, D = `player-${Math.random().toString(36).slice(2).toUpperCase()}`, O = [
|
||||||
|
"ready",
|
||||||
|
"play",
|
||||||
|
"pause",
|
||||||
|
"canplay",
|
||||||
|
"playing",
|
||||||
|
"ended",
|
||||||
|
"liveStreamStop",
|
||||||
|
"onM3u8Retry",
|
||||||
|
"hideBar",
|
||||||
|
"showBar",
|
||||||
|
"waiting",
|
||||||
|
"timeupdate",
|
||||||
|
"snapshoted",
|
||||||
|
"requestFullScreen",
|
||||||
|
"cancelFullScreen",
|
||||||
|
"error",
|
||||||
|
"startSeek",
|
||||||
|
"completeSeek"
|
||||||
|
], k = e(() => h.cssLink || (h.sdkVersion ? p(h.sdkVersion) : u)), A = e(() => h.scriptSrc || (h.sdkVersion ? m(h.sdkVersion) : d)), j = e(() => h.normalizeSourceUrl ? x(h.source) : h.source), M = e(() => b(j.value)), N = e(() => {
|
||||||
|
let e = {
|
||||||
|
width: "100%",
|
||||||
|
autoplay: !0,
|
||||||
|
...h.options || {},
|
||||||
|
...h.license ? { license: h.license } : {},
|
||||||
|
...j.value ? { source: j.value } : {},
|
||||||
|
id: D
|
||||||
|
};
|
||||||
|
return h.autoFormat && M.value && !e.format && (e.format = M.value), h.lowLatency && e.isLive && M.value === "flv" && (e.enableStashBufferForFlv = e.enableStashBufferForFlv ?? !1, e.stashInitialSizeForFlv = e.stashInitialSizeForFlv ?? 128), e;
|
||||||
|
});
|
||||||
|
function P() {
|
||||||
|
return y.value;
|
||||||
|
}
|
||||||
|
function F() {
|
||||||
|
y.value && (y.value.dispose(), y.value = null, w.value = null);
|
||||||
|
}
|
||||||
|
function I(e) {
|
||||||
|
O.forEach((t) => {
|
||||||
|
e.on(t, (e) => {
|
||||||
|
g(t, e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function L(e) {
|
||||||
|
if (!h.forbidFastForward) return;
|
||||||
|
let t = 0, n = 0;
|
||||||
|
e.on("timeupdate", () => {
|
||||||
|
let r = e.getCurrentTime();
|
||||||
|
if (r - t > 2) {
|
||||||
|
e.seek(t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t = r, t >= n && (n = t);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function R() {
|
||||||
|
if (C.value || !window.Aliplayer || !S.value) return;
|
||||||
|
F();
|
||||||
|
let e = window.Aliplayer({ ...N.value });
|
||||||
|
y.value = e, w.value = M.value, I(e), L(e);
|
||||||
|
}
|
||||||
|
async function z() {
|
||||||
|
let e = ++E;
|
||||||
|
try {
|
||||||
|
if (h.disableTracking && T(h.trackingUrlPatterns), await _(k.value, A.value), await v(h.componentScripts), await r(), C.value || e !== E) return;
|
||||||
|
R();
|
||||||
|
} catch (e) {
|
||||||
|
g("sdk-error", e instanceof Error ? e : Error(String(e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function B(e) {
|
||||||
|
if (e && y.value) {
|
||||||
|
y.value.loadByUrl(h.normalizeSourceUrl && x(e) || e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await z();
|
||||||
|
}
|
||||||
|
async function V(e) {
|
||||||
|
await B(e);
|
||||||
|
}
|
||||||
|
function H() {
|
||||||
|
y.value?.play();
|
||||||
|
}
|
||||||
|
function U() {
|
||||||
|
y.value?.pause();
|
||||||
|
}
|
||||||
|
function W() {
|
||||||
|
y.value?.replay();
|
||||||
|
}
|
||||||
|
function G(e) {
|
||||||
|
y.value?.seek(e);
|
||||||
|
}
|
||||||
|
function K() {
|
||||||
|
return y.value?.getCurrentTime();
|
||||||
|
}
|
||||||
|
function ee() {
|
||||||
|
return y.value?.getDuration();
|
||||||
|
}
|
||||||
|
function q() {
|
||||||
|
return y.value?.getVolume();
|
||||||
|
}
|
||||||
|
function J(e) {
|
||||||
|
y.value?.setVolume(e);
|
||||||
|
}
|
||||||
|
function Y(e, t) {
|
||||||
|
y.value?.loadByUrl(e, t);
|
||||||
|
}
|
||||||
|
function X(e, t) {
|
||||||
|
y.value?.replayByVidAndPlayAuth(e, t);
|
||||||
|
}
|
||||||
|
function Z(e, t, n, r, i, a) {
|
||||||
|
y.value?.replayByVidAndAuthInfo(e, t, n, r, i, a);
|
||||||
|
}
|
||||||
|
function Q(e, t) {
|
||||||
|
y.value?.setPlayerSize(e, t);
|
||||||
|
}
|
||||||
|
function $(e) {
|
||||||
|
y.value?.setSpeed(e);
|
||||||
|
}
|
||||||
|
function te(e, t, n) {
|
||||||
|
y.value?.setSanpshotProperties(e, t, n);
|
||||||
|
}
|
||||||
|
function ne() {
|
||||||
|
y.value?.fullscreenService?.requestFullScreen();
|
||||||
|
}
|
||||||
|
function re() {
|
||||||
|
y.value?.fullscreenService?.cancelFullScreen();
|
||||||
|
}
|
||||||
|
function ie() {
|
||||||
|
return y.value?.fullscreenService?.getIsFullScreen();
|
||||||
|
}
|
||||||
|
function ae() {
|
||||||
|
return y.value?.getStatus();
|
||||||
|
}
|
||||||
|
function oe(e, t) {
|
||||||
|
y.value?.liveShiftSerivce?.setLiveTimeRange(e, t);
|
||||||
|
}
|
||||||
|
function se(e) {
|
||||||
|
y.value?.setRotate(e);
|
||||||
|
}
|
||||||
|
function ce() {
|
||||||
|
return y.value?.getRotate();
|
||||||
|
}
|
||||||
|
function le(e) {
|
||||||
|
y.value?.setImage(e);
|
||||||
|
}
|
||||||
|
function ue(e) {
|
||||||
|
y.value?.setCover(e);
|
||||||
|
}
|
||||||
|
function de(e) {
|
||||||
|
y.value?.setProgressMarkers(e);
|
||||||
|
}
|
||||||
|
function fe(e) {
|
||||||
|
y.value?.setPreviewTime(e);
|
||||||
|
}
|
||||||
|
function pe() {
|
||||||
|
return y.value?.getPreviewTime();
|
||||||
|
}
|
||||||
|
function me() {
|
||||||
|
return y.value?.isPreview();
|
||||||
|
}
|
||||||
|
function he(e, t) {
|
||||||
|
y.value?.off?.(e, t);
|
||||||
|
}
|
||||||
|
return a(() => {
|
||||||
|
z();
|
||||||
|
}), c(() => j.value, (e) => {
|
||||||
|
if (!e) return;
|
||||||
|
let t = b(e);
|
||||||
|
if (y.value && t && t === w.value) {
|
||||||
|
y.value.loadByUrl(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
z();
|
||||||
|
}), c(() => [
|
||||||
|
h.options,
|
||||||
|
h.forbidFastForward,
|
||||||
|
h.license,
|
||||||
|
h.lowLatency,
|
||||||
|
h.autoFormat,
|
||||||
|
h.sdkVersion,
|
||||||
|
h.cssLink,
|
||||||
|
h.scriptSrc,
|
||||||
|
h.componentScripts,
|
||||||
|
h.disableTracking,
|
||||||
|
h.trackingUrlPatterns
|
||||||
|
], () => {
|
||||||
|
z();
|
||||||
|
}, { deep: !0 }), i(() => {
|
||||||
|
C.value = !0, E += 1, F();
|
||||||
|
}), l({
|
||||||
|
getPlayer: P,
|
||||||
|
init: z,
|
||||||
|
initPlayer: R,
|
||||||
|
reload: B,
|
||||||
|
retry: V,
|
||||||
|
play: H,
|
||||||
|
pause: U,
|
||||||
|
replay: W,
|
||||||
|
seek: G,
|
||||||
|
getCurrentTime: K,
|
||||||
|
getDuration: ee,
|
||||||
|
getVolume: q,
|
||||||
|
setVolume: J,
|
||||||
|
loadByUrl: Y,
|
||||||
|
replayByVidAndPlayAuth: X,
|
||||||
|
replayByVidAndAuthInfo: Z,
|
||||||
|
setPlayerSize: Q,
|
||||||
|
setSpeed: $,
|
||||||
|
setSanpshotProperties: te,
|
||||||
|
requestFullScreen: ne,
|
||||||
|
cancelFullScreen: re,
|
||||||
|
getIsFullScreen: ie,
|
||||||
|
getStatus: ae,
|
||||||
|
setLiveTimeRange: oe,
|
||||||
|
setRotate: se,
|
||||||
|
getRotate: ce,
|
||||||
|
setImage: le,
|
||||||
|
dispose: F,
|
||||||
|
setCover: ue,
|
||||||
|
setProgressMarkers: de,
|
||||||
|
setPreviewTime: fe,
|
||||||
|
getPreviewTime: pe,
|
||||||
|
isPreview: me,
|
||||||
|
off: he
|
||||||
|
}), (e, n) => (o(), t("div", {
|
||||||
|
id: D,
|
||||||
|
ref_key: "containerRef",
|
||||||
|
ref: S,
|
||||||
|
class: "vue-aliplayer-v2"
|
||||||
|
}, null, 512));
|
||||||
|
}
|
||||||
|
}), [["__scopeId", "data-v-cf852d0d"]]), D = {
|
||||||
|
sdkVersion: l,
|
||||||
|
cssLink: u,
|
||||||
|
scriptSrc: d,
|
||||||
|
componentScripts: [],
|
||||||
|
disableTracking: !1,
|
||||||
|
trackingUrlPatterns: []
|
||||||
|
}, O = E;
|
||||||
|
O.install = (e, t) => {
|
||||||
|
Object.assign(D, t || {}), e.component("VueAliplayerV2", O);
|
||||||
|
}, O.props.cssLink.default = () => D.cssLink, O.props.scriptSrc.default = () => D.scriptSrc, O.props.sdkVersion.default = () => D.sdkVersion, O.props.componentScripts.default = () => D.componentScripts, O.props.disableTracking.default = () => D.disableTracking, O.props.trackingUrlPatterns.default = () => D.trackingUrlPatterns, O.Player = O;
|
||||||
|
//#endregion
|
||||||
|
export { O as VueAliplayerV2, O as default };
|
||||||
1
lib/vue-aliplayer-v2.umd.cjs
Normal file
1
lib/vue-aliplayer-v2.umd.cjs
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
2
lib/vue-aliplayer-v2.umd.min.js
vendored
2
lib/vue-aliplayer-v2.umd.min.js
vendored
File diff suppressed because one or more lines are too long
1250
package-lock.json
generated
Normal file
1250
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@ -1,31 +1,41 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-aliplayer-v2",
|
"name": "vue-aliplayer-v2",
|
||||||
"version": "1.3.1",
|
"version": "2.0.0",
|
||||||
|
"type": "module",
|
||||||
"author": "yxs",
|
"author": "yxs",
|
||||||
"description": "感谢每一位支持开源的朋友. 这是一个基于Alipayer 开发并封装成vue组件的集成播放器.可播放rtmp,m3u8,mp4....视频.除支持直播流与点播的基础功能外,也支持视频的加密播放、清晰度切换、直播时移等业务场景",
|
"description": "Vue 3 wrapper for Aliyun Aliplayer. Supports mp4, m3u8, flv, live streams, encrypted playback, quality switching, and live time shift through the official Aliplayer SDK.",
|
||||||
"main": "lib/vue-aliplayer-v2.umd.min.js",
|
"main": "lib/vue-aliplayer-v2.umd.cjs",
|
||||||
|
"module": "lib/vue-aliplayer-v2.js",
|
||||||
|
"types": "lib/types/index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./lib/types/index.d.ts",
|
||||||
|
"import": "./lib/vue-aliplayer-v2.js",
|
||||||
|
"require": "./lib/vue-aliplayer-v2.umd.cjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
"private": false,
|
"private": false,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vue-cli-service serve",
|
"dev": "vite --host 0.0.0.0",
|
||||||
"build": "vue-cli-service build",
|
"build": "vite build --mode demo",
|
||||||
"lint": "vue-cli-service lint",
|
"type-check": "vue-tsc --noEmit",
|
||||||
"lib": "vue-cli-service build --target lib --name vue-aliplayer-v2 --dest lib packages/index.js"
|
"lib": "vue-tsc -p tsconfig.build.json --declaration --emitDeclarationOnly --outDir lib/types && vite build --mode lib",
|
||||||
|
"lint": "vue-tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^2.6.5",
|
"vue": "^3.5.34"
|
||||||
"vue": "^2.6.10"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^3.8.0",
|
"@types/node": "^24.10.0",
|
||||||
"@vue/cli-plugin-eslint": "^3.8.0",
|
"@vitejs/plugin-vue": "^6.0.7",
|
||||||
"@vue/cli-service": "^3.8.0",
|
"typescript": "^5.9.3",
|
||||||
"babel-eslint": "^10.0.1",
|
"vite": "^8.0.14",
|
||||||
"eslint": "^5.16.0",
|
"vue-tsc": "^3.3.1"
|
||||||
"eslint-plugin-vue": "^5.0.0",
|
|
||||||
"less": "^3.9.0",
|
|
||||||
"less-loader": "^5.0.0",
|
|
||||||
"vue-template-compiler": "^2.6.10"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@ -1,555 +1,386 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :id="playerId"></div>
|
<div :id="playerId" ref="containerRef" class="vue-aliplayer-v2"></div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup lang="ts">
|
||||||
name: 'VueAliplayerV2',
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||||
props: {
|
import {
|
||||||
forbidFastForward: { //禁止拖拽快进
|
DEFAULT_CSS_LINK,
|
||||||
required: false,
|
DEFAULT_SCRIPT_SRC,
|
||||||
type: [Boolean],
|
DEFAULT_SDK_VERSION,
|
||||||
default: false
|
getCssLinkByVersion,
|
||||||
},
|
getScriptSrcByVersion,
|
||||||
options: { //配置项
|
loadAliplayerSdk,
|
||||||
required: false,
|
loadExtraScripts
|
||||||
type: [Object],
|
} from './sdkLoader';
|
||||||
default: () => null
|
import { inferSourceFormat, normalizeSource, type SourceFormat } from './source';
|
||||||
},
|
import { installTrackingBlocker } from './tracking';
|
||||||
source: { //播放源(此属性存在则优先于options.source) 动态切换,目前只支持同种格式(mp4/flv/m3u8)之间切换。暂不支持直播rtmp流切换。
|
import type {
|
||||||
required: false,
|
AliplayerEventName,
|
||||||
type: [String],
|
AliplayerInstance,
|
||||||
default: null
|
AliplayerOptions,
|
||||||
},
|
AliplayerV2Props,
|
||||||
cssLink: { //css版本源
|
VueAliplayerV2Expose
|
||||||
required: false,
|
} from './types';
|
||||||
type: [String],
|
|
||||||
default: `https://g.alicdn.com/de/prismplayer/2.9.20/skins/default/aliplayer-min.css`
|
defineOptions({
|
||||||
},
|
name: 'VueAliplayerV2'
|
||||||
scriptSrc: { //js版本源
|
});
|
||||||
required: false,
|
|
||||||
type: [String],
|
const props = withDefaults(defineProps<AliplayerV2Props>(), {
|
||||||
default: `https://g.alicdn.com/de/prismplayer/2.9.20/aliplayer-min.js`
|
autoFormat: true,
|
||||||
}
|
componentScripts: () => [],
|
||||||
},
|
disableTracking: false,
|
||||||
data () {
|
forbidFastForward: false,
|
||||||
return {
|
license: null,
|
||||||
player: null, //播放器实例
|
lowLatency: false,
|
||||||
playerId: `player-${Math.random().toString(36).substr(2).toLocaleUpperCase()}`,
|
normalizeSourceUrl: true,
|
||||||
config: {
|
options: null,
|
||||||
id: null, //播放器的ID
|
sdkVersion: DEFAULT_SDK_VERSION,
|
||||||
|
source: null,
|
||||||
|
cssLink: '',
|
||||||
|
scriptSrc: '',
|
||||||
|
trackingUrlPatterns: () => []
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(event: AliplayerEventName, payload?: unknown): void;
|
||||||
|
(event: 'sdk-error', error: Error): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const player = ref<AliplayerInstance | null>(null);
|
||||||
|
const containerRef = ref<HTMLDivElement | null>(null);
|
||||||
|
const isUnmounted = ref(false);
|
||||||
|
const currentFormat = ref<SourceFormat>(null);
|
||||||
|
let initToken = 0;
|
||||||
|
const playerId = `player-${Math.random().toString(36).slice(2).toUpperCase()}`;
|
||||||
|
const eventNames: AliplayerEventName[] = [
|
||||||
|
'ready',
|
||||||
|
'play',
|
||||||
|
'pause',
|
||||||
|
'canplay',
|
||||||
|
'playing',
|
||||||
|
'ended',
|
||||||
|
'liveStreamStop',
|
||||||
|
'onM3u8Retry',
|
||||||
|
'hideBar',
|
||||||
|
'showBar',
|
||||||
|
'waiting',
|
||||||
|
'timeupdate',
|
||||||
|
'snapshoted',
|
||||||
|
'requestFullScreen',
|
||||||
|
'cancelFullScreen',
|
||||||
|
'error',
|
||||||
|
'startSeek',
|
||||||
|
'completeSeek'
|
||||||
|
];
|
||||||
|
|
||||||
|
const resolvedCssLink = computed(() => props.cssLink || (props.sdkVersion ? getCssLinkByVersion(props.sdkVersion) : DEFAULT_CSS_LINK));
|
||||||
|
const resolvedScriptSrc = computed(() => props.scriptSrc || (props.sdkVersion ? getScriptSrcByVersion(props.sdkVersion) : DEFAULT_SCRIPT_SRC));
|
||||||
|
const normalizedSource = computed(() => props.normalizeSourceUrl ? normalizeSource(props.source) : props.source);
|
||||||
|
const sourceFormat = computed(() => inferSourceFormat(normalizedSource.value));
|
||||||
|
const mergedOptions = computed<AliplayerOptions>(() => {
|
||||||
|
const options: AliplayerOptions = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
// isLive: true,
|
...(props.options || {}),
|
||||||
//支持播放地址播放,此播放优先级最高
|
...(props.license ? { license: props.license } : {}),
|
||||||
// source: 'rtmp://182.145.195.238:1935/hls/1194076936807170050',
|
...(normalizedSource.value ? { source: normalizedSource.value } : {}),
|
||||||
},
|
id: playerId
|
||||||
events: [
|
|
||||||
/**
|
|
||||||
* 播放器视频初始化按钮渲染完毕。
|
|
||||||
* 播放器UI初始设置需要此事件后触发,避免UI被初始化所覆盖。
|
|
||||||
* 播放器提供的方法需要在此事件发生后才可以调用。
|
|
||||||
*/
|
|
||||||
'ready',
|
|
||||||
/**
|
|
||||||
* 视频由暂停恢复为播放时触发。
|
|
||||||
*/
|
|
||||||
'play',
|
|
||||||
/**
|
|
||||||
* 视频暂停时触发。
|
|
||||||
*/
|
|
||||||
'pause',
|
|
||||||
/**
|
|
||||||
* 能够开始播放音频/视频时发生,会多次触发,仅H5播放器。
|
|
||||||
*/
|
|
||||||
'canplay',
|
|
||||||
/**
|
|
||||||
* 播放中,会触发多次。
|
|
||||||
*/
|
|
||||||
'playing',
|
|
||||||
/**
|
|
||||||
* 当前视频播放完毕时触发。
|
|
||||||
*/
|
|
||||||
'ended',
|
|
||||||
/**
|
|
||||||
* 直播流中断时触发。
|
|
||||||
* m3u8/flv/rtmp在重试5次未成功后触发。
|
|
||||||
* 提示上层流中断或需要重新加载视频。
|
|
||||||
* PS:m3u8一直自动重试,不需要上层添加重试。
|
|
||||||
*/
|
|
||||||
'liveStreamStop',
|
|
||||||
/**
|
|
||||||
* m3u8直播流中断后重试事件,每次断流只触发一次。
|
|
||||||
*/
|
|
||||||
'onM3u8Retry',
|
|
||||||
/**
|
|
||||||
* 控制栏自动隐藏事件。
|
|
||||||
*/
|
|
||||||
'hideBar',
|
|
||||||
/**
|
|
||||||
* 控制栏自动显示事件。
|
|
||||||
*/
|
|
||||||
'showBar',
|
|
||||||
/**
|
|
||||||
* 数据缓冲事件。
|
|
||||||
*/
|
|
||||||
'waiting',
|
|
||||||
/**
|
|
||||||
* 播放位置发生改变时触发,仅H5播放器。
|
|
||||||
* 可通过getCurrentTime方法,得到当前播放时间。
|
|
||||||
*/
|
|
||||||
'timeupdate',
|
|
||||||
/**
|
|
||||||
* 截图完成。
|
|
||||||
*/
|
|
||||||
'snapshoted',
|
|
||||||
/**
|
|
||||||
* 全屏事件,仅H5支持。
|
|
||||||
*/
|
|
||||||
'requestFullScreen',
|
|
||||||
/**
|
|
||||||
* 取消全屏事件,iOS下不会触发,仅H5支持。
|
|
||||||
*/
|
|
||||||
'cancelFullScreen',
|
|
||||||
/**
|
|
||||||
* 错误事件。
|
|
||||||
*/
|
|
||||||
'error',
|
|
||||||
/**
|
|
||||||
* 开始拖拽,参数返回拖拽点的时间。
|
|
||||||
*/
|
|
||||||
'startSeek',
|
|
||||||
/**
|
|
||||||
* 完成拖拽,参数返回拖拽点的时间。
|
|
||||||
*/
|
|
||||||
'completeSeek'
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
source () { //监听播放源变化
|
|
||||||
this.init();
|
|
||||||
},
|
|
||||||
forbidFastForward () {
|
|
||||||
this.init();
|
|
||||||
|
|
||||||
},
|
if (props.autoFormat && sourceFormat.value && !options.format) {
|
||||||
|
options.format = sourceFormat.value;
|
||||||
options: { //配置项是对象,只能深度监听
|
|
||||||
handler () {
|
|
||||||
this.init();
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted () {
|
if (props.lowLatency && options.isLive && sourceFormat.value === 'flv') {
|
||||||
this.$nextTick(() => {
|
options.enableStashBufferForFlv = options.enableStashBufferForFlv ?? false;
|
||||||
this.init();
|
options.stashInitialSizeForFlv = options.stashInitialSizeForFlv ?? 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
});
|
});
|
||||||
},
|
|
||||||
updated () {
|
|
||||||
//重载播放器
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.init();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handlerFastForward () {
|
|
||||||
|
|
||||||
},
|
function getPlayer(): AliplayerInstance | null {
|
||||||
/**
|
return player.value;
|
||||||
* 创建script和css
|
|
||||||
* 加载Alipayer的SDK
|
|
||||||
*/
|
|
||||||
init () {
|
|
||||||
const linkID = 'app__aliplayer-min-css';
|
|
||||||
const scriptID = 'app__aliplayer-min-js';
|
|
||||||
const head = document.getElementsByTagName('head');
|
|
||||||
const html = document.getElementsByTagName('html');
|
|
||||||
let scriptTag = document.getElementById(scriptID);
|
|
||||||
let linkIDTag = document.getElementById(linkID);
|
|
||||||
if (!linkIDTag) {
|
|
||||||
// console.log('linkIDTag');
|
|
||||||
const link = document.createElement('link');
|
|
||||||
link.type = 'text/css';
|
|
||||||
link.rel = 'stylesheet';
|
|
||||||
link.href = this.cssLink;
|
|
||||||
link.id = linkID;
|
|
||||||
// link.className = linkID;
|
|
||||||
head[0].appendChild(link);
|
|
||||||
}
|
}
|
||||||
if (!scriptTag) {
|
|
||||||
// console.log('scriptTag');
|
|
||||||
scriptTag = document.createElement('script');
|
|
||||||
scriptTag.type = "text/javascript";
|
|
||||||
scriptTag.id = scriptID;
|
|
||||||
// scriptTag.className = scriptID;
|
|
||||||
scriptTag.src = this.scriptSrc;
|
|
||||||
html[0].appendChild(scriptTag);
|
|
||||||
} else {
|
|
||||||
this.initPlayer(); //这样是为了兼容页面上有多个播放器
|
|
||||||
}
|
|
||||||
//兼容单页加载和硬加载
|
|
||||||
scriptTag.addEventListener("load", () => {
|
|
||||||
this.initPlayer();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
function dispose(): void {
|
||||||
* 创建播放器
|
if (!player.value) return;
|
||||||
* @description SDK文档地址:https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.6.1084.131d1c4cJT7o5Z
|
player.value.dispose();
|
||||||
*/
|
player.value = null;
|
||||||
initPlayer () {
|
currentFormat.value = null;
|
||||||
if (typeof window.Aliplayer != 'undefined') {
|
|
||||||
const options = this.deepCloneObject(this.options);
|
|
||||||
if (options) {
|
|
||||||
for (const key in options) {
|
|
||||||
this.config[key] = options[key];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (this.source) this.config.source = this.source; //播放源
|
function bindEvents(target: AliplayerInstance): void {
|
||||||
this.config.id = this.playerId; //赋值播放器容器id
|
eventNames.forEach((eventName) => {
|
||||||
this.player && this.player.dispose(); //防止实例的重复
|
target.on(eventName, (event?: unknown) => {
|
||||||
this.player = Aliplayer(this.config);
|
emit(eventName, event);
|
||||||
for (const ev in this.events) {
|
});
|
||||||
this.player && this.player.on(this.events[ev], (e) => {
|
|
||||||
// console.log(`object ${this.events[ev]}`,e);
|
|
||||||
this.$emit(this.events[ev], e);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bindForbidFastForward(target: AliplayerInstance): void {
|
||||||
|
if (!props.forbidFastForward) return;
|
||||||
|
|
||||||
//开启禁止拖拽快进
|
let last = 0;
|
||||||
if (this.forbidFastForward) {
|
let maxTime = 0;
|
||||||
let last = 0, max_time = 0;
|
target.on('timeupdate', () => {
|
||||||
this.player.on('timeupdate', function () {
|
const current = target.getCurrentTime();
|
||||||
let current = this.getCurrentTime();
|
|
||||||
if (current - last > 2) {
|
if (current - last > 2) {
|
||||||
this.seek(last);
|
target.seek(last);
|
||||||
} else {
|
return;
|
||||||
last = current;
|
|
||||||
if (last >= max_time) {
|
|
||||||
max_time = last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last = current;
|
||||||
|
if (last >= maxTime) {
|
||||||
|
maxTime = last;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过播放器实例的off方法取消订阅
|
function initPlayer(): void {
|
||||||
//player.off('ready',handleReady);
|
if (isUnmounted.value || !window.Aliplayer || !containerRef.value) return;
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
dispose();
|
||||||
* @return player 实例
|
const nextPlayer = window.Aliplayer({ ...mergedOptions.value });
|
||||||
*/
|
player.value = nextPlayer;
|
||||||
getPlayer () {
|
currentFormat.value = sourceFormat.value;
|
||||||
return this.player;
|
bindEvents(nextPlayer);
|
||||||
},
|
bindForbidFastForward(nextPlayer);
|
||||||
|
|
||||||
/**
|
|
||||||
* 播放视频。
|
|
||||||
*/
|
|
||||||
play () {
|
|
||||||
// console.log(`播放视频。`);
|
|
||||||
this.player && this.player.play();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 暂停视频
|
|
||||||
*/
|
|
||||||
pause () {
|
|
||||||
// console.log(`暂停视频`);
|
|
||||||
this.player && this.player.pause();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重播视频
|
|
||||||
*/
|
|
||||||
replay () {
|
|
||||||
// console.log(`重播视频`);
|
|
||||||
this.player && this.player.replay();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳转到某个时刻进行播放,time的单位为秒。
|
|
||||||
* @param time
|
|
||||||
* @return player
|
|
||||||
*/
|
|
||||||
seek (time) {
|
|
||||||
// console.log(`跳转到某个时刻进行播放,time为${time}秒。`);
|
|
||||||
this.player && this.player.seek(time);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前的播放时刻,返回的单位为秒。
|
|
||||||
* @return player
|
|
||||||
*/
|
|
||||||
getCurrentTime () {
|
|
||||||
// console.log(`获取当前的播放时刻,返回的单位为${this.player && this.player.getCurrentTime()}秒。`);
|
|
||||||
return this.player && this.player.getCurrentTime();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频总时长,返回的单位为秒,这个需要在视频加载完成以后才可以获取到,可以在play事件后获取。
|
|
||||||
* @return player
|
|
||||||
*/
|
|
||||||
getDuration () {
|
|
||||||
// console.log(`获取视频总时长,返回的单位为${this.player && this.player.getDuration()}秒。`);
|
|
||||||
return this.player && this.player.getDuration();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前的音量,返回值为0-1的实数。ios和部分android会失效。
|
|
||||||
* @return player
|
|
||||||
*/
|
|
||||||
getVolume () {
|
|
||||||
// console.log(`获取当前的音量${this.player && this.player.getVolume()}。`);
|
|
||||||
return this.player && this.player.getVolume();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置音量,vol为0-1的实数,ios和部分android会失效。
|
|
||||||
* @return player
|
|
||||||
*/
|
|
||||||
setVolume (v) {
|
|
||||||
// console.log(`设置音量,vol为${v}。`);
|
|
||||||
this.player && this.player.setVolume(v);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直接播放视频url,time为可选值(单位秒)。目前只支持同种格式(mp4/flv/m3u8)之间切换。
|
|
||||||
* 暂不支持直播rtmp流切换。
|
|
||||||
* @return player
|
|
||||||
*/
|
|
||||||
loadByUrl (url, time) {
|
|
||||||
// console.log(`直接播放视频url${url},time为${time}。`);
|
|
||||||
this.player && this.player.loadByUrl(url, time);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 目前只支持H5播放器。暂不支持不同格式视频间的之间切换。暂不支持直播rtmp流切换。
|
|
||||||
* @param vid 视频id
|
|
||||||
* @param 播放凭证
|
|
||||||
*/
|
|
||||||
replayByVidAndPlayAuth (vid, playauth) {
|
|
||||||
// console.log(`replayByVidAndPlayAuth vid${vid},playauth为${playauth}。`);
|
|
||||||
this.player && this.player.replayByVidAndPlayAuth(vid, playauth);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 目前只支持H5播放器。暂不支持不同格式视频间的之间切换。暂不支持直播rtmp流切换。
|
|
||||||
* @param vid 视频id
|
|
||||||
* @param 播放凭证
|
|
||||||
* @description 仅MPS用户时使用 仅MPS用户时使用 参数顺序为:vid、accId、accSecret、stsToken、authInfo、domainRegion
|
|
||||||
*/
|
|
||||||
replayByVidAndAuthInfo (vid, accId, accSecret, stsToken, authInfo, domainRegion) {
|
|
||||||
// console.log(`replayByVidAndAuthInfo 参数顺序为:vid、accId、accSecret、stsToken、authInfo、domainRegion`,vid, accId, accSecret, stsToken, authInfo, domainRegion);
|
|
||||||
this.player && this.player.replayByVidAndAuthInfo(vid, accId, accSecret, stsToken, authInfo, domainRegion);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置播放器大小w,h可分别为400px像素或60%百分比。
|
|
||||||
* @param w 宽度
|
|
||||||
* @param h 宽度
|
|
||||||
* @description chrome浏览器下flash播放器分别不能小于397x297。
|
|
||||||
*/
|
|
||||||
setPlayerSize (w, h) {
|
|
||||||
// console.log(`设置播放器大小 宽度:${w},高度:${h}`);
|
|
||||||
this.player && this.player.setPlayerSize(w, h);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手动设置播放的倍速,倍速播放仅H5支持。移动端可能会失效,比如android微信。
|
|
||||||
* 倍速播放UI默认是开启的。
|
|
||||||
* 如果自定义过skinLaout属性,需要添加speedButton项到数组里:
|
|
||||||
* @param h 宽度
|
|
||||||
* @description {name:“speedButton”,align:“tr”,x:10,y:23}
|
|
||||||
*/
|
|
||||||
setSpeed (speed) {
|
|
||||||
// console.log(`手动设置播放的倍速:${speed}`);
|
|
||||||
this.player && this.player.setSpeed(speed);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置截图参数
|
|
||||||
* @param width 宽度
|
|
||||||
* @param height 高度
|
|
||||||
* @param rate 截图质量
|
|
||||||
*/
|
|
||||||
setSanpshotProperties (width, height, rate) {
|
|
||||||
// console.log(`设置截图参数:`,width, height, rate);
|
|
||||||
this.player && this.player.setSanpshotProperties(width, height, rate);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 播放器全屏,仅H5支持。
|
|
||||||
*/
|
|
||||||
requestFullScreen () {
|
|
||||||
// console.log(`播放器全屏,仅H5支持`);
|
|
||||||
this.player && this.player.fullscreenService && this.player.fullscreenService.requestFullScreen();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 播放器退出全屏,iOS调用无效,仅H5支持。
|
|
||||||
*/
|
|
||||||
cancelFullScreen () {
|
|
||||||
// console.log(`播放器全屏,仅H5支持`);
|
|
||||||
this.player && this.player.fullscreenService && this.player.fullscreenService.cancelFullScreen();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取播放器全屏状态,仅H5支持。
|
|
||||||
*/
|
|
||||||
getIsFullScreen () {
|
|
||||||
// console.log(`获取播放器全屏状态,仅H5支持。`,this.player && this.player.fullscreenService && this.player && this.player.fullscreenService.getIsFullScreen());
|
|
||||||
return this.player && this.player.fullscreenService && this.player.fullscreenService.getIsFullScreen();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取播放器状态,包含的值,
|
|
||||||
* @returns init ready loading play pause playing waiting error ended
|
|
||||||
*/
|
|
||||||
getStatus () {
|
|
||||||
// console.log(`获取播放器状态,包含的值`,this.player && this.player.fullscreenService && this.player && this.player.fullscreenService.getStatus());
|
|
||||||
return this.player && this.player.getStatus();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置直播的开始结束时间,开启直播时移功能时使用。
|
|
||||||
* @param beginTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @description 例子:player.liveShiftSerivce.setLiveTimeRange(“”,‘2018/01/04 20:00:00’)
|
|
||||||
*/
|
|
||||||
setLiveTimeRange (beginTime, endTime) {
|
|
||||||
// console.log(`设置直播的开始时间:${beginTime},结束时间:${endTime},开启直播时移功能时使用。`);
|
|
||||||
this.player && this.player.liveShiftSerivce && this.player.liveShiftSerivce.setLiveTimeRange(beginTime, endTime);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 参数为旋转角度, 正数为正时针旋转, 负数为逆时针旋转。
|
|
||||||
* @param rotate 旋转角度
|
|
||||||
* @description 例如: setRotate(90)。详情参见旋转和镜像。
|
|
||||||
*/
|
|
||||||
setRotate (rotate) {
|
|
||||||
// console.log(`参数为旋转角度:${rotate}。`);
|
|
||||||
this.player && this.player.setRotate(rotate);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取旋转角度。详情参见旋转和镜像。
|
|
||||||
* @return rotate 旋转角度
|
|
||||||
*/
|
|
||||||
getRotate () {
|
|
||||||
// console.log(`获取旋转角度:${this.player && this.player.getRotate()}`);
|
|
||||||
return this.player && this.player.getRotate();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置镜像
|
|
||||||
* @param image 镜像类型 可选值为:horizon,vertical
|
|
||||||
* @description 例如: setImage(‘horizon’)。详情参见旋转和镜像。
|
|
||||||
*/
|
|
||||||
setImage (image) {
|
|
||||||
// console.log(`设置镜像:${image}。`);
|
|
||||||
this.player && this.player.setImage(image);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 播放器销毁
|
|
||||||
*/
|
|
||||||
dispose () {
|
|
||||||
// console.log(`播放器销毁。`);
|
|
||||||
this.player && this.player.dispose();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置封面
|
|
||||||
* @param cover 封面地址
|
|
||||||
*/
|
|
||||||
setCover (cover) {
|
|
||||||
// console.log(`设置封面:${cover}`);
|
|
||||||
this.player && this.player.setCover(cover);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置封面
|
|
||||||
* @param markers 设置打点数据
|
|
||||||
*/
|
|
||||||
setProgressMarkers (markers) {
|
|
||||||
// console.log(`markers打点数据集合:${markers}`);
|
|
||||||
this.player && this.player.setProgressMarkers(markers);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置试看时间,单位为秒,详情参见
|
|
||||||
* @param time 试看时间
|
|
||||||
*/
|
|
||||||
setPreviewTime (time) {
|
|
||||||
// console.log(`设置试看时间,单位为:${time}秒`);
|
|
||||||
this.player && this.player.setPreviewTime(time);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取试看时间
|
|
||||||
* @return rotate 旋转角度
|
|
||||||
*/
|
|
||||||
getPreviewTime () {
|
|
||||||
// console.log(`获取试看时间:${this.player && this.player.getPreviewTime()}`);
|
|
||||||
return this.player && this.player.getPreviewTime();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否试看
|
|
||||||
*/
|
|
||||||
isPreview () {
|
|
||||||
// console.log(`是否试看`);
|
|
||||||
this.player && this.player.isPreview();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ev 事件名
|
|
||||||
* @param handle 回调方法
|
|
||||||
*/
|
|
||||||
off (ev, handle) {
|
|
||||||
this.player && this.player.off(ev, handle);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 深度拷贝
|
|
||||||
* @param {*} obj
|
|
||||||
*/
|
|
||||||
deepCloneObject (obj) {
|
|
||||||
let objClone = Array.isArray(obj) ? [] : {};
|
|
||||||
if (obj && typeof obj === 'object') {
|
|
||||||
for (let key in obj) {
|
|
||||||
if (obj.hasOwnProperty(key)) {
|
|
||||||
//判断ojb子元素是否为对象,如果是,递归复制
|
|
||||||
if (obj[key] && typeof obj[key] === 'object') {
|
|
||||||
objClone[key] = this.deepCloneObject(obj[key]);
|
|
||||||
} else {
|
|
||||||
//如果不是,简单复制
|
|
||||||
objClone[key] = obj[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return objClone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
async function init(): Promise<void> {
|
||||||
beforeDestroy () { //防止重复创建
|
const token = ++initToken;
|
||||||
this.dispose(); //销毁播放器(防止直播播放的情况下,播放器已经销毁,而后台还在继续下载资源造成卡顿的bug)
|
try {
|
||||||
// const head = document.querySelector('head');
|
if (props.disableTracking) {
|
||||||
// const cssNodes = document.querySelectorAll(`link.app__aliplayer-min-css`);
|
installTrackingBlocker(props.trackingUrlPatterns);
|
||||||
// (html && cssNodes.length > 1) && cssNodes.forEach((item, index)=>{
|
|
||||||
// if(index != 0) head.removeChild(item);
|
|
||||||
// });
|
|
||||||
// const html = document.querySelector('html');
|
|
||||||
// const jsNodes = document.querySelectorAll(`script.app__aliplayer-min-js`);
|
|
||||||
// (html && jsNodes.length > 1) && jsNodes.forEach((item, index)=>{
|
|
||||||
// if(index != 0) html.removeChild(item);
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
};
|
await loadAliplayerSdk(resolvedCssLink.value, resolvedScriptSrc.value);
|
||||||
|
await loadExtraScripts(props.componentScripts);
|
||||||
|
await nextTick();
|
||||||
|
if (isUnmounted.value || token !== initToken) return;
|
||||||
|
initPlayer();
|
||||||
|
} catch (error) {
|
||||||
|
emit('sdk-error', error instanceof Error ? error : new Error(String(error)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reload(nextSource?: string): Promise<void> {
|
||||||
|
if (nextSource && player.value) {
|
||||||
|
player.value.loadByUrl(props.normalizeSourceUrl ? normalizeSource(nextSource) || nextSource : nextSource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await init();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function retry(nextSource?: string): Promise<void> {
|
||||||
|
await reload(nextSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
function play(): void {
|
||||||
|
player.value?.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
function pause(): void {
|
||||||
|
player.value?.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
function replay(): void {
|
||||||
|
player.value?.replay();
|
||||||
|
}
|
||||||
|
|
||||||
|
function seek(time: number): void {
|
||||||
|
player.value?.seek(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentTime(): number | undefined {
|
||||||
|
return player.value?.getCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDuration(): number | undefined {
|
||||||
|
return player.value?.getDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVolume(): number | undefined {
|
||||||
|
return player.value?.getVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setVolume(volume: number): void {
|
||||||
|
player.value?.setVolume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadByUrl(url: string, time?: number): void {
|
||||||
|
player.value?.loadByUrl(url, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replayByVidAndPlayAuth(vid: string, playauth: string): void {
|
||||||
|
player.value?.replayByVidAndPlayAuth(vid, playauth);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replayByVidAndAuthInfo(
|
||||||
|
vid: string,
|
||||||
|
accId: string,
|
||||||
|
accSecret: string,
|
||||||
|
stsToken: string,
|
||||||
|
authInfo: string,
|
||||||
|
domainRegion: string
|
||||||
|
): void {
|
||||||
|
player.value?.replayByVidAndAuthInfo(vid, accId, accSecret, stsToken, authInfo, domainRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPlayerSize(width: string, height: string): void {
|
||||||
|
player.value?.setPlayerSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSpeed(speed: number): void {
|
||||||
|
player.value?.setSpeed(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSanpshotProperties(width: number, height: number, rate: number): void {
|
||||||
|
player.value?.setSanpshotProperties(width, height, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestFullScreen(): void {
|
||||||
|
player.value?.fullscreenService?.requestFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelFullScreen(): void {
|
||||||
|
player.value?.fullscreenService?.cancelFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIsFullScreen(): boolean | undefined {
|
||||||
|
return player.value?.fullscreenService?.getIsFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatus(): string | undefined {
|
||||||
|
return player.value?.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLiveTimeRange(beginTime: string, endTime: string): void {
|
||||||
|
player.value?.liveShiftSerivce?.setLiveTimeRange(beginTime, endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRotate(rotate: number): void {
|
||||||
|
player.value?.setRotate(rotate);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRotate(): number | undefined {
|
||||||
|
return player.value?.getRotate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setImage(image: string): void {
|
||||||
|
player.value?.setImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCover(cover: string): void {
|
||||||
|
player.value?.setCover(cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setProgressMarkers(markers: unknown[]): void {
|
||||||
|
player.value?.setProgressMarkers(markers);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPreviewTime(time: number): void {
|
||||||
|
player.value?.setPreviewTime(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPreviewTime(): number | undefined {
|
||||||
|
return player.value?.getPreviewTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPreview(): boolean | undefined {
|
||||||
|
return player.value?.isPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
function off(eventName: string, handler: (event?: unknown) => void): void {
|
||||||
|
player.value?.off?.(eventName, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
void init();
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => normalizedSource.value,
|
||||||
|
(source) => {
|
||||||
|
if (!source) return;
|
||||||
|
const nextFormat = inferSourceFormat(source);
|
||||||
|
if (player.value && nextFormat && nextFormat === currentFormat.value) {
|
||||||
|
player.value.loadByUrl(source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void init();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [
|
||||||
|
props.options,
|
||||||
|
props.forbidFastForward,
|
||||||
|
props.license,
|
||||||
|
props.lowLatency,
|
||||||
|
props.autoFormat,
|
||||||
|
props.sdkVersion,
|
||||||
|
props.cssLink,
|
||||||
|
props.scriptSrc,
|
||||||
|
props.componentScripts,
|
||||||
|
props.disableTracking,
|
||||||
|
props.trackingUrlPatterns
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
void init();
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
isUnmounted.value = true;
|
||||||
|
initToken += 1;
|
||||||
|
dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose<VueAliplayerV2Expose>({
|
||||||
|
getPlayer,
|
||||||
|
init,
|
||||||
|
initPlayer,
|
||||||
|
reload,
|
||||||
|
retry,
|
||||||
|
play,
|
||||||
|
pause,
|
||||||
|
replay,
|
||||||
|
seek,
|
||||||
|
getCurrentTime,
|
||||||
|
getDuration,
|
||||||
|
getVolume,
|
||||||
|
setVolume,
|
||||||
|
loadByUrl,
|
||||||
|
replayByVidAndPlayAuth,
|
||||||
|
replayByVidAndAuthInfo,
|
||||||
|
setPlayerSize,
|
||||||
|
setSpeed,
|
||||||
|
setSanpshotProperties,
|
||||||
|
requestFullScreen,
|
||||||
|
cancelFullScreen,
|
||||||
|
getIsFullScreen,
|
||||||
|
getStatus,
|
||||||
|
setLiveTimeRange,
|
||||||
|
setRotate,
|
||||||
|
getRotate,
|
||||||
|
setImage,
|
||||||
|
dispose,
|
||||||
|
setCover,
|
||||||
|
setProgressMarkers,
|
||||||
|
setPreviewTime,
|
||||||
|
getPreviewTime,
|
||||||
|
isPreview,
|
||||||
|
off
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.vue-aliplayer-v2 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
81
packages/AliplayerV2/sdkLoader.ts
Normal file
81
packages/AliplayerV2/sdkLoader.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
export const DEFAULT_SDK_VERSION = '2.37.0';
|
||||||
|
export const DEFAULT_CSS_LINK = `https://g.alicdn.com/apsara-media-box/imp-web-player/${DEFAULT_SDK_VERSION}/skins/default/aliplayer-min.css`;
|
||||||
|
export const DEFAULT_SCRIPT_SRC = `https://g.alicdn.com/apsara-media-box/imp-web-player/${DEFAULT_SDK_VERSION}/aliplayer-min.js`;
|
||||||
|
|
||||||
|
const scriptLoadPromises = new Map<string, Promise<void>>();
|
||||||
|
|
||||||
|
export function getCssLinkByVersion(version: string): string {
|
||||||
|
return `https://g.alicdn.com/apsara-media-box/imp-web-player/${version}/skins/default/aliplayer-min.css`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getScriptSrcByVersion(version: string): string {
|
||||||
|
return `https://g.alicdn.com/apsara-media-box/imp-web-player/${version}/aliplayer-min.js`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureStylesheet(cssLink: string): void {
|
||||||
|
if (!cssLink) return;
|
||||||
|
|
||||||
|
const existed = document.querySelector<HTMLLinkElement>(`link[data-vue-aliplayer-v2-css="${cssLink}"]`);
|
||||||
|
if (existed) return;
|
||||||
|
|
||||||
|
const link = document.createElement('link');
|
||||||
|
link.type = 'text/css';
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.href = cssLink;
|
||||||
|
link.dataset.vueAliplayerV2Css = cssLink;
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureScript(scriptSrc: string, globalName?: string): Promise<void> {
|
||||||
|
if (!scriptSrc) return Promise.resolve();
|
||||||
|
if (globalName && window[globalName]) return Promise.resolve();
|
||||||
|
if (scriptLoadPromises.has(scriptSrc)) return scriptLoadPromises.get(scriptSrc) as Promise<void>;
|
||||||
|
|
||||||
|
const existed = document.querySelector<HTMLScriptElement>(`script[data-vue-aliplayer-v2-js="${scriptSrc}"]`);
|
||||||
|
if (existed) {
|
||||||
|
const loadPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
if (existed.dataset.vueAliplayerV2Loaded === 'true') {
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
existed.addEventListener('load', () => {
|
||||||
|
existed.dataset.vueAliplayerV2Loaded = 'true';
|
||||||
|
resolve();
|
||||||
|
}, { once: true });
|
||||||
|
existed.addEventListener('error', () => reject(new Error(`Failed to load Aliplayer SDK: ${scriptSrc}`)), { once: true });
|
||||||
|
});
|
||||||
|
scriptLoadPromises.set(scriptSrc, loadPromise);
|
||||||
|
return loadPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.src = scriptSrc;
|
||||||
|
script.dataset.vueAliplayerV2Js = scriptSrc;
|
||||||
|
script.addEventListener('load', () => {
|
||||||
|
script.dataset.vueAliplayerV2Loaded = 'true';
|
||||||
|
resolve();
|
||||||
|
}, { once: true });
|
||||||
|
script.addEventListener('error', () => reject(new Error(`Failed to load Aliplayer SDK: ${scriptSrc}`)), { once: true });
|
||||||
|
document.documentElement.appendChild(script);
|
||||||
|
});
|
||||||
|
|
||||||
|
scriptLoadPromises.set(scriptSrc, loadPromise);
|
||||||
|
return loadPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared SDK loader. It prevents duplicate CSS/JS tags when several player
|
||||||
|
* instances mount at the same time or are recreated by route changes.
|
||||||
|
*/
|
||||||
|
export async function loadAliplayerSdk(cssLink: string, scriptSrc: string): Promise<void> {
|
||||||
|
ensureStylesheet(cssLink);
|
||||||
|
await ensureScript(scriptSrc, 'Aliplayer');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function loadExtraScripts(scriptUrls: string[] = []): Promise<void> {
|
||||||
|
for (const scriptUrl of scriptUrls) {
|
||||||
|
await ensureScript(scriptUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
packages/AliplayerV2/source.ts
Normal file
25
packages/AliplayerV2/source.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export type SourceFormat = 'mp4' | 'm3u8' | 'flv' | 'rtmp' | 'mp3' | null;
|
||||||
|
|
||||||
|
const KNOWN_FORMATS: SourceFormat[] = ['m3u8', 'flv', 'mp4', 'rtmp', 'mp3'];
|
||||||
|
|
||||||
|
export function inferSourceFormat(source?: string | null): SourceFormat {
|
||||||
|
if (!source) return null;
|
||||||
|
|
||||||
|
if (/^rtmps?:\/\//i.test(source)) return 'rtmp';
|
||||||
|
|
||||||
|
const cleanSource = source.split('?')[0].split('#')[0].toLowerCase();
|
||||||
|
const matched = KNOWN_FORMATS.find((format) => format && cleanSource.endsWith(`.${format}`));
|
||||||
|
return matched || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeSource(source?: string | null): string | null {
|
||||||
|
if (!source) return source || null;
|
||||||
|
if (/^(data|blob):/i.test(source)) return source;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return encodeURI(source);
|
||||||
|
} catch {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
49
packages/AliplayerV2/tracking.ts
Normal file
49
packages/AliplayerV2/tracking.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
const DEFAULT_TRACKING_PATTERNS: Array<string | RegExp> = [
|
||||||
|
'videocloud.cn-hangzhou.log.aliyuncs.com/logstores/newplayer/track'
|
||||||
|
];
|
||||||
|
|
||||||
|
let trackingBlockerInstalled = false;
|
||||||
|
|
||||||
|
function matchesTrackingUrl(url: string, patterns: Array<string | RegExp>): boolean {
|
||||||
|
return patterns.some((pattern) => {
|
||||||
|
if (typeof pattern === 'string') return url.includes(pattern);
|
||||||
|
return pattern.test(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function installTrackingBlocker(patterns: Array<string | RegExp> = DEFAULT_TRACKING_PATTERNS): void {
|
||||||
|
if (trackingBlockerInstalled) return;
|
||||||
|
trackingBlockerInstalled = true;
|
||||||
|
|
||||||
|
const originalFetch = window.fetch?.bind(window);
|
||||||
|
if (originalFetch) {
|
||||||
|
window.fetch = ((input: RequestInfo | URL, init?: RequestInit) => {
|
||||||
|
const url = typeof input === 'string' || input instanceof URL ? String(input) : input.url;
|
||||||
|
if (matchesTrackingUrl(url, patterns)) {
|
||||||
|
return Promise.resolve(new Response(null, { status: 204, statusText: 'No Content' }));
|
||||||
|
}
|
||||||
|
return originalFetch(input, init);
|
||||||
|
}) as typeof window.fetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalOpen = XMLHttpRequest.prototype.open;
|
||||||
|
const originalSend = XMLHttpRequest.prototype.send;
|
||||||
|
|
||||||
|
XMLHttpRequest.prototype.open = function open(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null): void {
|
||||||
|
this.__vueAliplayerV2Blocked = matchesTrackingUrl(String(url), patterns);
|
||||||
|
originalOpen.call(this, method, url, async ?? true, username ?? undefined, password ?? undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLHttpRequest.prototype.send = function send(body?: Document | XMLHttpRequestBodyInit | null): void {
|
||||||
|
if (this.__vueAliplayerV2Blocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
originalSend.call(this, body);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface XMLHttpRequest {
|
||||||
|
__vueAliplayerV2Blocked?: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
170
packages/AliplayerV2/types.ts
Normal file
170
packages/AliplayerV2/types.ts
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import type { Plugin } from 'vue';
|
||||||
|
|
||||||
|
export interface VueAliplayerV2Options {
|
||||||
|
sdkVersion?: string;
|
||||||
|
cssLink?: string;
|
||||||
|
scriptSrc?: string;
|
||||||
|
componentScripts?: string[];
|
||||||
|
disableTracking?: boolean;
|
||||||
|
trackingUrlPatterns?: Array<string | RegExp>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AliplayerV2Props extends VueAliplayerV2Options {
|
||||||
|
autoFormat?: boolean;
|
||||||
|
forbidFastForward?: boolean;
|
||||||
|
license?: AliplayerLicense | null;
|
||||||
|
lowLatency?: boolean;
|
||||||
|
normalizeSourceUrl?: boolean;
|
||||||
|
options?: AliplayerOptions | null;
|
||||||
|
source?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AliplayerLicense {
|
||||||
|
domain: string;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AliplayerEventName =
|
||||||
|
| 'ready'
|
||||||
|
| 'play'
|
||||||
|
| 'pause'
|
||||||
|
| 'canplay'
|
||||||
|
| 'playing'
|
||||||
|
| 'ended'
|
||||||
|
| 'liveStreamStop'
|
||||||
|
| 'onM3u8Retry'
|
||||||
|
| 'hideBar'
|
||||||
|
| 'showBar'
|
||||||
|
| 'waiting'
|
||||||
|
| 'timeupdate'
|
||||||
|
| 'snapshoted'
|
||||||
|
| 'requestFullScreen'
|
||||||
|
| 'cancelFullScreen'
|
||||||
|
| 'error'
|
||||||
|
| 'startSeek'
|
||||||
|
| 'completeSeek';
|
||||||
|
|
||||||
|
export interface AliplayerOptions {
|
||||||
|
id?: string;
|
||||||
|
source?: string;
|
||||||
|
width?: string;
|
||||||
|
autoplay?: boolean;
|
||||||
|
isLive?: boolean;
|
||||||
|
format?: string;
|
||||||
|
license?: AliplayerLicense;
|
||||||
|
vid?: string;
|
||||||
|
playauth?: string;
|
||||||
|
accessKeyId?: string;
|
||||||
|
securityToken?: string;
|
||||||
|
accessKeySecret?: string;
|
||||||
|
region?: string;
|
||||||
|
authTimeout?: number;
|
||||||
|
components?: unknown[];
|
||||||
|
enableStashBufferForFlv?: boolean;
|
||||||
|
stashInitialSizeForFlv?: number;
|
||||||
|
rtsVersion?: string;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AliplayerFullscreenService {
|
||||||
|
requestFullScreen: () => void;
|
||||||
|
cancelFullScreen: () => void;
|
||||||
|
getIsFullScreen: () => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AliplayerLiveShiftService {
|
||||||
|
setLiveTimeRange: (beginTime: string, endTime: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AliplayerInstance {
|
||||||
|
on: (eventName: string, handler: (event?: unknown) => void) => void;
|
||||||
|
off?: (eventName: string, handler: (event?: unknown) => void) => void;
|
||||||
|
play: () => void;
|
||||||
|
pause: () => void;
|
||||||
|
replay: () => void;
|
||||||
|
seek: (time: number) => void;
|
||||||
|
getCurrentTime: () => number;
|
||||||
|
getDuration: () => number;
|
||||||
|
getVolume: () => number;
|
||||||
|
setVolume: (volume: number) => void;
|
||||||
|
loadByUrl: (url: string, time?: number) => void;
|
||||||
|
replayByVidAndPlayAuth: (vid: string, playauth: string) => void;
|
||||||
|
replayByVidAndAuthInfo: (
|
||||||
|
vid: string,
|
||||||
|
accId: string,
|
||||||
|
accSecret: string,
|
||||||
|
stsToken: string,
|
||||||
|
authInfo: string,
|
||||||
|
domainRegion: string
|
||||||
|
) => void;
|
||||||
|
setPlayerSize: (width: string, height: string) => void;
|
||||||
|
setSpeed: (speed: number) => void;
|
||||||
|
setSanpshotProperties: (width: number, height: number, rate: number) => void;
|
||||||
|
fullscreenService?: AliplayerFullscreenService;
|
||||||
|
getStatus: () => string;
|
||||||
|
liveShiftSerivce?: AliplayerLiveShiftService;
|
||||||
|
setRotate: (rotate: number) => void;
|
||||||
|
getRotate: () => number;
|
||||||
|
setImage: (image: string) => void;
|
||||||
|
dispose: () => void;
|
||||||
|
setCover: (cover: string) => void;
|
||||||
|
setProgressMarkers: (markers: unknown[]) => void;
|
||||||
|
setPreviewTime: (time: number) => void;
|
||||||
|
getPreviewTime: () => number;
|
||||||
|
isPreview: () => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VueAliplayerV2Expose {
|
||||||
|
getPlayer: () => AliplayerInstance | null;
|
||||||
|
init: () => Promise<void>;
|
||||||
|
initPlayer: () => void;
|
||||||
|
reload: (nextSource?: string) => Promise<void>;
|
||||||
|
retry: (nextSource?: string) => Promise<void>;
|
||||||
|
play: () => void;
|
||||||
|
pause: () => void;
|
||||||
|
replay: () => void;
|
||||||
|
seek: (time: number) => void;
|
||||||
|
getCurrentTime: () => number | undefined;
|
||||||
|
getDuration: () => number | undefined;
|
||||||
|
getVolume: () => number | undefined;
|
||||||
|
setVolume: (volume: number) => void;
|
||||||
|
loadByUrl: (url: string, time?: number) => void;
|
||||||
|
replayByVidAndPlayAuth: (vid: string, playauth: string) => void;
|
||||||
|
replayByVidAndAuthInfo: (
|
||||||
|
vid: string,
|
||||||
|
accId: string,
|
||||||
|
accSecret: string,
|
||||||
|
stsToken: string,
|
||||||
|
authInfo: string,
|
||||||
|
domainRegion: string
|
||||||
|
) => void;
|
||||||
|
setPlayerSize: (width: string, height: string) => void;
|
||||||
|
setSpeed: (speed: number) => void;
|
||||||
|
setSanpshotProperties: (width: number, height: number, rate: number) => void;
|
||||||
|
requestFullScreen: () => void;
|
||||||
|
cancelFullScreen: () => void;
|
||||||
|
getIsFullScreen: () => boolean | undefined;
|
||||||
|
getStatus: () => string | undefined;
|
||||||
|
setLiveTimeRange: (beginTime: string, endTime: string) => void;
|
||||||
|
setRotate: (rotate: number) => void;
|
||||||
|
getRotate: () => number | undefined;
|
||||||
|
setImage: (image: string) => void;
|
||||||
|
dispose: () => void;
|
||||||
|
setCover: (cover: string) => void;
|
||||||
|
setProgressMarkers: (markers: unknown[]) => void;
|
||||||
|
setPreviewTime: (time: number) => void;
|
||||||
|
getPreviewTime: () => number | undefined;
|
||||||
|
isPreview: () => boolean | undefined;
|
||||||
|
off: (eventName: string, handler: (event?: unknown) => void) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VueAliplayerV2Plugin = Plugin & {
|
||||||
|
Player?: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
Aliplayer?: (options: AliplayerOptions) => AliplayerInstance;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
// packages / index.js
|
|
||||||
// 导入单个组件
|
|
||||||
import VueAliplayerV2 from './AliplayerV2';
|
|
||||||
// 定义 install 方法
|
|
||||||
VueAliplayerV2.install = (Vue, options) =>{
|
|
||||||
if(options && options.cssLink) VueAliplayerV2.props.cssLink.default = options.cssLink;
|
|
||||||
if(options && options.scriptSrc) VueAliplayerV2.props.scriptSrc.default = options.scriptSrc;
|
|
||||||
Vue.component(VueAliplayerV2.name, VueAliplayerV2);
|
|
||||||
};
|
|
||||||
VueAliplayerV2.Player = VueAliplayerV2;
|
|
||||||
export default VueAliplayerV2;
|
|
||||||
54
packages/index.ts
Normal file
54
packages/index.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import type { App } from 'vue';
|
||||||
|
import VueAliplayerV2 from './AliplayerV2/index.vue';
|
||||||
|
import { DEFAULT_CSS_LINK, DEFAULT_SCRIPT_SRC, DEFAULT_SDK_VERSION } from './AliplayerV2/sdkLoader';
|
||||||
|
import type { VueAliplayerV2Options } from './AliplayerV2/types';
|
||||||
|
|
||||||
|
export type {
|
||||||
|
AliplayerEventName,
|
||||||
|
AliplayerInstance,
|
||||||
|
AliplayerLicense,
|
||||||
|
AliplayerOptions,
|
||||||
|
AliplayerV2Props,
|
||||||
|
VueAliplayerV2Expose,
|
||||||
|
VueAliplayerV2Options
|
||||||
|
} from './AliplayerV2/types';
|
||||||
|
|
||||||
|
type InstallableVueAliplayerV2 = typeof VueAliplayerV2 & {
|
||||||
|
install: (app: App, options?: VueAliplayerV2Options) => void;
|
||||||
|
Player: typeof VueAliplayerV2;
|
||||||
|
props: {
|
||||||
|
sdkVersion: { default: string | (() => string) };
|
||||||
|
cssLink: { default: string | (() => string) };
|
||||||
|
scriptSrc: { default: string | (() => string) };
|
||||||
|
componentScripts: { default: string[] | (() => string[]) };
|
||||||
|
disableTracking: { default: boolean | (() => boolean) };
|
||||||
|
trackingUrlPatterns: { default: Array<string | RegExp> | (() => Array<string | RegExp>) };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const globalOptions: Required<VueAliplayerV2Options> = {
|
||||||
|
sdkVersion: DEFAULT_SDK_VERSION,
|
||||||
|
cssLink: DEFAULT_CSS_LINK,
|
||||||
|
scriptSrc: DEFAULT_SCRIPT_SRC,
|
||||||
|
componentScripts: [],
|
||||||
|
disableTracking: false,
|
||||||
|
trackingUrlPatterns: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const installable = VueAliplayerV2 as unknown as InstallableVueAliplayerV2;
|
||||||
|
|
||||||
|
installable.install = (app: App, options?: VueAliplayerV2Options): void => {
|
||||||
|
Object.assign(globalOptions, options || {});
|
||||||
|
app.component('VueAliplayerV2', installable);
|
||||||
|
};
|
||||||
|
|
||||||
|
installable.props.cssLink.default = (): string => globalOptions.cssLink;
|
||||||
|
installable.props.scriptSrc.default = (): string => globalOptions.scriptSrc;
|
||||||
|
installable.props.sdkVersion.default = (): string => globalOptions.sdkVersion;
|
||||||
|
installable.props.componentScripts.default = (): string[] => globalOptions.componentScripts;
|
||||||
|
installable.props.disableTracking.default = (): boolean => globalOptions.disableTracking;
|
||||||
|
installable.props.trackingUrlPatterns.default = (): Array<string | RegExp> => globalOptions.trackingUrlPatterns;
|
||||||
|
installable.Player = installable;
|
||||||
|
|
||||||
|
export { installable as VueAliplayerV2 };
|
||||||
|
export default installable;
|
||||||
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
autoprefixer: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
|
||||||
<title>vue-aliplayer-v2</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>
|
|
||||||
<strong>We're sorry but vue-aliplayer-v2 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- built files will be auto injected -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
5
tsconfig.build.json
Normal file
5
tsconfig.build.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"include": ["packages/**/*.ts", "packages/**/*.vue", "env.d.ts"],
|
||||||
|
"exclude": ["examples/**", "dist/**", "lib/**", "node_modules/**"]
|
||||||
|
}
|
||||||
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"env.d.ts",
|
||||||
|
"examples/**/*.ts",
|
||||||
|
"examples/**/*.vue",
|
||||||
|
"packages/**/*.ts",
|
||||||
|
"packages/**/*.vue",
|
||||||
|
"vite.config.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
36
vite.config.ts
Normal file
36
vite.config.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
|
||||||
|
export default defineConfig(({ mode }) => {
|
||||||
|
const isDemoBuild = mode === 'demo';
|
||||||
|
|
||||||
|
return {
|
||||||
|
base: isDemoBuild ? '/vue-aliplayer-v2/' : '/',
|
||||||
|
plugins: [vue()],
|
||||||
|
publicDir: isDemoBuild ? 'public' : false,
|
||||||
|
build: isDemoBuild
|
||||||
|
? {
|
||||||
|
outDir: 'dist',
|
||||||
|
emptyOutDir: true
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
outDir: 'lib',
|
||||||
|
emptyOutDir: false,
|
||||||
|
lib: {
|
||||||
|
entry: resolve(__dirname, 'packages/index.ts'),
|
||||||
|
name: 'VueAliplayerV2',
|
||||||
|
fileName: 'vue-aliplayer-v2'
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: ['vue'],
|
||||||
|
output: {
|
||||||
|
exports: 'named',
|
||||||
|
globals: {
|
||||||
|
vue: 'Vue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
@ -1,15 +0,0 @@
|
|||||||
// vue.config.js
|
|
||||||
module.exports = {
|
|
||||||
// 将 examples 目录添加为新的页面
|
|
||||||
pages: {
|
|
||||||
index: {
|
|
||||||
// page 的入口
|
|
||||||
entry: 'examples/main.js',
|
|
||||||
// 模板来源
|
|
||||||
template: 'public/index.html',
|
|
||||||
// 输出文件名
|
|
||||||
filename: 'index.html'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
publicPath: process.env.NODE_ENV === "production" ? "/vue-aliplayer-v2" : "/"
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user