├── 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 | }) --------------------------------------------------------------------------------