├── app.ttss
├── app.js
├── .DS_Store
├── pages
├── .DS_Store
├── index
│ ├── index.json
│ ├── index.ttml
│ ├── index.ttss
│ └── index.js
├── play
│ ├── index.ttss
│ ├── index.json
│ ├── index.js
│ └── index.ttml
├── video-player
│ ├── .DS_Store
│ ├── index.ttss
│ ├── index.json
│ ├── index.ttml
│ └── index.js
└── wrap-player
│ ├── index.json
│ ├── index.ttss
│ ├── index.ttml
│ └── index.js
├── project.private.config.json
├── project.config.json
├── app.json
└── README.md
/app.ttss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | App({
2 | onLaunch: function () {
3 |
4 | }
5 | })
6 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dengzemiao/Toutiao-video-player/HEAD/.DS_Store
--------------------------------------------------------------------------------
/pages/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dengzemiao/Toutiao-video-player/HEAD/pages/.DS_Store
--------------------------------------------------------------------------------
/project.private.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "setting": {
3 | "urlCheck": false
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {},
3 | "navigationBarTitleText":"短剧 video-player"
4 | }
--------------------------------------------------------------------------------
/pages/index/index.ttml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/pages/play/index.ttss:
--------------------------------------------------------------------------------
1 | .video-view {
2 | width: 100vw;
3 | height: 100vh;
4 | background-color: yellow;
5 | }
--------------------------------------------------------------------------------
/pages/video-player/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dengzemiao/Toutiao-video-player/HEAD/pages/video-player/.DS_Store
--------------------------------------------------------------------------------
/pages/video-player/index.ttss:
--------------------------------------------------------------------------------
1 | /* 兼容 uniapp 第三方混编使用,不需要可移除,详细查看 README.md */
2 | .video-player-view {
3 | width: 100%;
4 | height: 100%;
5 | }
--------------------------------------------------------------------------------
/pages/wrap-player/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "video-player":"/pages/video-player/index"
5 | }
6 | }
--------------------------------------------------------------------------------
/pages/video-player/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "video-player":"ext://industry/video-player"
5 | }
6 | }
--------------------------------------------------------------------------------
/pages/index/index.ttss:
--------------------------------------------------------------------------------
1 | .video-content {
2 | width: 100vw;
3 | height: 100vh;
4 | display: flex;
5 | align-items: center;
6 | justify-content: center;
7 | background-color: red;
8 | }
9 |
--------------------------------------------------------------------------------
/pages/wrap-player/index.ttss:
--------------------------------------------------------------------------------
1 | .wrap-player {
2 | width: 100vw;
3 | height: 100vh;
4 | }
5 | .video-view {
6 | width: 100vw;
7 | height: 50vh;
8 | background-color: greenyellow;
9 | }
--------------------------------------------------------------------------------
/pages/play/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "video-player":"/pages/video-player/index",
4 | "wrap-player": "/pages/wrap-player/index"
5 | },
6 | "navigationBarTitleText":"播放页"
7 | }
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {"setting":{"urlCheck":true,"es6":true,"postcss":true,"minified":true,"newFeature":true,"autoCompile":true,"compileHotReLoad":true},"appid":"tt67d91164f8e5ae6701","projectname":"video-player","douyinProjectType":"native"}
2 |
--------------------------------------------------------------------------------
/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const app = getApp()
2 |
3 | Page({
4 | data: {
5 | },
6 | onLoad: function () {
7 | },
8 | jumpPlay () {
9 | tt.navigateTo({
10 | url: '/pages/play/index',
11 | success: (res) => {
12 | },
13 | fail: (res) => {
14 | },
15 | });
16 | }
17 | })
18 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/play/index"
5 | ],
6 | "window": {
7 | "backgroundTextStyle": "light",
8 | "navigationBarBackgroundColor": "#fff",
9 | "navigationBarTitleText": "Mini Program",
10 | "navigationBarTextStyle": "black"
11 | }
12 | }
--------------------------------------------------------------------------------
/pages/play/index.js:
--------------------------------------------------------------------------------
1 | const app = getApp()
2 |
3 | Page({
4 | data: {
5 | },
6 | onLoad: function () {
7 | console.log(tt.canIUse('video-player'))
8 | },
9 | binderror (e) {
10 | console.log('binderror', e)
11 | },
12 | bindplay (e) {
13 | console.log('playhandler', e)
14 | },
15 | bindtimeupdate (e) {
16 | console.log('bindtimeupdate', e)
17 | }
18 | })
19 |
--------------------------------------------------------------------------------
/pages/play/index.ttml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/pages/wrap-player/index.ttml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/pages/wrap-player/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {
3 | // 播放器上下文
4 | context: undefined,
5 | // 播放器 ref
6 | counter: undefined
7 | },
8 | methods: {
9 | bindref(ref) {
10 | // 获取上下文,ref 用于拿不到上下文时传入第二个参数
11 | // const context = tt.createVideoContext('my-video-player', ref)
12 | const context = tt.createVideoContext('my-video-player')
13 | // 记录
14 | this.setData({
15 | context,
16 | counter: ref
17 | })
18 | },
19 | binderror(e) {
20 | // console.log('binderror', e)
21 | },
22 | bindplay(e) {
23 | // console.log('playhandler', e)
24 | },
25 | bindtimeupdate(e) {
26 | // console.log('bindtimeupdate', e)
27 | },
28 | touchPlay() {
29 | this.data.context.play()
30 | },
31 | touchPause() {
32 | this.data.context.pause()
33 | }
34 | }
35 | })
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Toutiao-video-player
2 |
3 | - 抖音短剧播放器 video-player 原生组件封装,可用于 uniapp、原生抖小短剧项目使用。
4 |
5 | - 官方对接文档:
6 |
7 | - Uniapp 对接抖音短剧播放器 video-player 坑点解决:
8 |
9 | - `video-player.ttml 与 video-player.ttss` 中的加了 `class: video-player-view` 是为了解决 `uniapp` 混编的问题,纯原生开发可以移除这个样式即可。
10 |
11 | 原因:因为 `uniapp` 在使用 `video-player` 组件时,会形成两层包裹 `uniapp video-player` 包裹 `原生 video-player`,导致使用 `inner-class` 会无法设置样式,原生就没问题,这个时候有两种方式解决:
12 |
13 | 1、直接传 `inner-style` 样式进去,不走 `inner-class`
14 |
15 | 2、(推荐)直接给 `uniapp video-player` 设置 `class` 正常设置样式,然后给 `原生 video-player` 的 `class: video-player-view` 内部宽高百分百,这样就能正常沿用外面的尺寸。
16 |
17 | 3、(推荐)直接给 `uniapp video-player` 设置 `class` 正常设置样式,然后给 `原生 video-player` 的 `inner-style` 设置宽高百分百,这样也能正常沿用外面的尺寸。
18 |
19 | - 目录结构:
20 |
21 | ```sh
22 | - pages
23 | - index # 首页
24 | - play # 播放页,包含:1、直接使用播放组件 2、播放组件被组件嵌套使用
25 | - video-player # 播放组件
26 | - wrap-player # 对播放组件再次包裹一层组件测试,包含上下文获取实现播放跟暂停
27 | ```
28 |
--------------------------------------------------------------------------------
/pages/video-player/index.ttml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/video-player/index.js:
--------------------------------------------------------------------------------
1 | // 自定义组件参考:https://mp.kuaishou.com/docs/develop/frame/custom_comp/component_constructor.html
2 | // video 参考:https://bytedance.larkoffice.com/docx/TsJmdbX6co33uJxi7j9cfYc2nnd
3 | // 可使用 tt.canIUse('video-player') 判断是否支持最新播放器
4 | // 基础库 2.77.0 开始支持本组件,基础库只在抖音、抖极、抖火 23.8 及以上版本支持
5 | Component({
6 | // 外部样式属性定义,其实也就是把内部需要外部支持的 class 名称放这里导出
7 | // 在外部直接使用导出的名称字段关联即可,可以同时导出多个,这里是数组 ['','',...]
8 | externalClasses: ['inner-class'],
9 | // 对内参数
10 | data: {
11 | },
12 | // 对外参数(prop)
13 | properties: {
14 | // 内部样式
15 | innerStyle: {
16 | type: String,
17 | value: ''
18 | },
19 | // 唯一标识符
20 | id: {
21 | type: String,
22 | value: ''
23 | },
24 | // 原片id
25 | albumId: {
26 | type: String,
27 | value: ''
28 | },
29 | // 剧集id
30 | episodeId: {
31 | type: String,
32 | value: ''
33 | },
34 | // 废弃字段。为了兼容老版本,请传 1
35 | version: {
36 | type: String,
37 | value: '1'
38 | },
39 | // 使用cdn类型,1: 抖音云 2: 三方云
40 | cloudType: {
41 | type: Number,
42 | value: 1
43 | },
44 | // 播放地址,cloudType 为 2 时生效,传入第三方播放地址 http://vjs.zencdn.net/v/oceans.mp4
45 | src: {
46 | type: String,
47 | value: ''
48 | },
49 | // 自动播放
50 | autoplay: {
51 | type: Boolean,
52 | value: false
53 | },
54 | // 显示默认播放控件(播放/暂停按钮、播放进度、时间)
55 | controls: {
56 | type: Boolean,
57 | value: true
58 | },
59 | // 循环播放
60 | loop: {
61 | type: Boolean,
62 | value: false
63 | },
64 | // 静音播放
65 | muted: {
66 | type: Boolean,
67 | value: false
68 | },
69 | // 指定视频初始播放位置
70 | initialTime: {
71 | type: Number,
72 | value: 0
73 | },
74 | // 指定视频时长
75 | duration: {
76 | type: Number,
77 | value: 0
78 | },
79 | // 'contain' | 'fill' | 'cover'
80 | objectFit: {
81 | type: String,
82 | value: 'contain'
83 | },
84 | // 若不设置,宽度大于 240 时才会显示
85 | showProgress: {
86 | type: Boolean,
87 | value: true
88 | },
89 | // 是否显示全屏按钮
90 | // 在同层渲染模式下仅支持控制竖屏状态(非全屏)下的「全屏按钮」的显示,横屏状态(全屏)不显示「退出全屏按钮」,只能通过标题旁边的箭头退出全屏
91 | showFullscreenBtn: {
92 | type: Boolean,
93 | value: true
94 | },
95 | // 是否显示视频底部控制栏的播放按钮
96 | showPlayBtn: {
97 | type: Boolean,
98 | value: true
99 | },
100 | // 是否开启控制进度的手势
101 | enableProgressGesture: {
102 | type: Boolean,
103 | value: true
104 | },
105 | // 是否显示静音按钮
106 | showMuteBtn: {
107 | type: Boolean,
108 | value: false
109 | }
110 | },
111 | methods: {
112 | // 加载 ref
113 | refHandler(ref) {
114 | this.triggerEvent('ref', ref)
115 | },
116 | // 当开始/继续播放时触发 play 事件
117 | handlePlay(e) {
118 | this.triggerEvent('play', e)
119 | },
120 | // 当暂停播放时触发 pause 事件
121 | handlePause(e) {
122 | this.triggerEvent('pause', e)
123 | },
124 | // 当播放到末尾时触发 ended 事件
125 | handleEnded(e) {
126 | this.triggerEvent('ended', e)
127 | },
128 | // 播放进度变化时触发,event.detail = {currentTime, duration} 。触发频率 250ms 一次
129 | handleTimeupdate(e) {
130 | this.triggerEvent('timeupdate', e)
131 | },
132 | // 视频进入和退出全屏时触发,event.detail = {fullScreen, direction},direction 有效值为 vertical 或 horizontal
133 | handleFullscreenchange(e) {
134 | this.triggerEvent('fullscreenchange', e)
135 | },
136 | // bindgetsource 表示 video-player 组件内部资源获取完成。如果使用 VideoContext 播放,需在这个时机后播放,否则可能出现播放失败。
137 | // 可用 tt.canIUse('video-player.bindgetsource') 校验是否支持该事件,如果不支持需作降级处理。
138 | handleGetsource (e) {
139 | this.triggerEvent('getsource', e)
140 | },
141 | // 视频播放出错时触发
142 | handleError(e) {
143 | this.triggerEvent('error', e)
144 | }
145 | }
146 | })
--------------------------------------------------------------------------------