player.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. <template>
  2. <div id="dplayer" ref="dplayer">
  3. <v-dialog
  4. v-model="permissionDialog"
  5. max-width="290"
  6. >
  7. <v-card>
  8. <v-card-title class="headline">VIP 观看</v-card-title>
  9. <v-card-text>
  10. <span>您还不是 VIP, 本视频仅供 VIP 观看</span>
  11. </v-card-text>
  12. <v-card-actions>
  13. <v-spacer />
  14. <v-btn
  15. color="green darken-1"
  16. text
  17. @click="gotoHomePage"
  18. >
  19. 好的呢
  20. </v-btn>
  21. <v-btn
  22. color="green darken-1"
  23. text
  24. @click="gotoVipPage"
  25. >
  26. 成为 VIP
  27. </v-btn>
  28. </v-card-actions>
  29. </v-card>
  30. </v-dialog>
  31. <v-dialog
  32. v-model="authCodeDialog"
  33. max-width="290"
  34. >
  35. <v-form
  36. ref="form"
  37. lazy-validation
  38. >
  39. <v-text-field
  40. v-model="authCode"
  41. label="验证码"
  42. required
  43. />
  44. <v-btn
  45. color="success"
  46. class="mr-4"
  47. @click="submitAuthCode"
  48. >
  49. 提交
  50. </v-btn>
  51. <v-btn
  52. color="error"
  53. class="mr-4"
  54. @click="cancelSubmitAuthCode"
  55. >
  56. 取消
  57. </v-btn>
  58. </v-form>
  59. </v-dialog>
  60. </div>
  61. </template>
  62. <script>
  63. import { videoUrl, submitPlayRecord } from '@/api/media/video'
  64. // import SocketInstance from '@/utils/ws/socket-instance'
  65. const hls = require('hls.js')
  66. const dashjs = require('dashjs')
  67. const flv = require('flv.js')
  68. const DPlayer = require('dplayer')
  69. export default {
  70. name: 'Play',
  71. props: {
  72. videoProp: {
  73. type: Object,
  74. default: () => null
  75. }
  76. },
  77. data() {
  78. return {
  79. hls,
  80. dashjs,
  81. flv,
  82. DPlayer,
  83. userPermission: {
  84. userId: -1,
  85. vip: false
  86. },
  87. userId: -1,
  88. playRecord: null,
  89. getUrl: false,
  90. permissionDialog: false,
  91. authCodeDialog: false,
  92. authCode: null
  93. }
  94. },
  95. created() {
  96. const userInfo = this.$store.state.user.userInfo
  97. if (userInfo !== null) {
  98. this.userPermission.userId = userInfo.userId
  99. this.userPermission.vip = userInfo.vip
  100. }
  101. const vidScope = this.videoProp.scope
  102. if (vidScope === 1) {
  103. this.getUrl = true
  104. } else if (vidScope === 2) {
  105. if (this.userPermission.vip) {
  106. this.getUrl = true
  107. } else {
  108. this.permissionDialog = true
  109. }
  110. } else if (vidScope === 3) {
  111. this.authCodeDialog = true
  112. } else if (vidScope === 4) {
  113. alert('私有视频, 只有本人可以观看')
  114. }
  115. },
  116. mounted() {
  117. // SocketInstance.connect()
  118. const videoId = this.videoProp.videoId
  119. if (this.getUrl) {
  120. this.getVideoUrl(videoId)
  121. /* videoUrl(videoId)
  122. .then(res => {
  123. if (res.code === 0) {
  124. const urlType = res.data.type
  125. if (urlType === 'mp4') {
  126. const urls = res.data.urls
  127. for (const url of urls) {
  128. url.type = 'normal'
  129. }
  130. this.initMp4Player(this.userPermission.userId, videoId, this.videoProp.coverUrl, urls)
  131. } else if (urlType === 'flv') {
  132. // this.initFlvPlayer(videoId, coverUrl, urls)
  133. } else {
  134. alert('url 类型无法识别')
  135. }
  136. } else {
  137. console.error(res.msg)
  138. }
  139. }).catch(error => {
  140. console.error(error.message)
  141. })*/
  142. }
  143. },
  144. methods: {
  145. getVideoUrl(videoId) {
  146. videoUrl(videoId)
  147. .then(res => {
  148. if (res.code === 0) {
  149. const urlType = res.data.type
  150. if (urlType === 'mp4') {
  151. const urls = res.data.urls
  152. for (const url of urls) {
  153. url.type = 'normal'
  154. }
  155. this.initMp4Player(this.userPermission.userId, videoId, this.videoProp.coverUrl, urls)
  156. } else if (urlType === 'flv') {
  157. // this.initFlvPlayer(videoId, coverUrl, urls)
  158. } else {
  159. alert('url 类型无法识别')
  160. }
  161. } else {
  162. console.error(res.msg)
  163. }
  164. }).catch(error => {
  165. console.error(error.message)
  166. })
  167. },
  168. // TODO 获取弹幕配置,将 videoUrl 作为本函数的回调
  169. danmakuConfig() {
  170. },
  171. submitVideoPlayRecord(currentTime) {
  172. if (this.playRecord == null) {
  173. return
  174. }
  175. this.playRecord.currentTime = currentTime
  176. submitPlayRecord(this.playRecord)
  177. .then(res => {
  178. if (res.code === 0) {
  179. console.log('播放进度已发送')
  180. } else {
  181. console.error(res.msg)
  182. }
  183. }).catch(error => {
  184. console.error(error.message)
  185. })
  186. },
  187. initMp4Player(userId, videoId, coverUrl, urls) {
  188. new DPlayer({
  189. container: document.querySelector('#dplayer'),
  190. lang: 'zh-cn',
  191. logo: '/logo.png',
  192. autoplay: false,
  193. screenshot: false,
  194. video: {
  195. pic: coverUrl,
  196. defaultQuality: 0,
  197. quality: urls
  198. // url: videoUrl
  199. // type: 'auto',
  200. },
  201. danmaku: {
  202. id: videoId,
  203. maximum: 10000,
  204. api: '//api.reghao.cn/api/comment/danmaku/',
  205. token: 'bili',
  206. user: userId,
  207. bottom: '15%',
  208. unlimited: true
  209. }
  210. })
  211. /* if (userId !== 0) {
  212. console.log('初始化 playRecord')
  213. this.playRecord = {
  214. 'userId': this.userPermission.userId,
  215. 'videoId': videoId,
  216. 'currentTime': 0.0
  217. }
  218. }
  219. // 跳转到指定秒
  220. // dp.seek(100)
  221. player.on('play', function() {
  222. console.log('mp4Player 开始播放事件' + this.userPermission.userId)
  223. console.log(this.playRecord)
  224. if (this.playRecord == null) {
  225. return
  226. }
  227. this.playRecord.currentTime = player.video.currentTime
  228. submitPlayRecord(this.playRecord)
  229. .then(res => {
  230. }).catch(error => {
  231. console.error(error.message)
  232. })
  233. })
  234. player.on('pause', function() {
  235. if (this.playRecord == null) {
  236. return
  237. }
  238. this.playRecord.currentTime = player.video.currentTime
  239. submitPlayRecord(this.playRecord)
  240. .then(res => {
  241. }).catch(error => {
  242. console.error(error.message)
  243. })
  244. })
  245. player.on('ended', function() {
  246. // TODO 当前视频播放完成后判断是否继续播放相关推荐中的视频
  247. if (this.playRecord == null) {
  248. return
  249. }
  250. this.playRecord.currentTime = player.video.currentTime
  251. submitPlayRecord(this.playRecord)
  252. .then(res => {
  253. }).catch(error => {
  254. console.error(error.message)
  255. })
  256. })
  257. player.on('seeking', function() {
  258. if (this.playRecord == null) {
  259. return
  260. }
  261. this.playRecord.currentTime = player.video.currentTime
  262. submitPlayRecord(this.playRecord)
  263. .then(res => {
  264. }).catch(error => {
  265. console.error(error.message)
  266. })
  267. })
  268. player.on('seeked', function() {
  269. if (this.playRecord == null) {
  270. return
  271. }
  272. this.playRecord.currentTime = player.video.currentTime
  273. submitPlayRecord(this.playRecord)
  274. .then(res => {
  275. }).catch(error => {
  276. console.error(error.message)
  277. })
  278. })
  279. var i = 0
  280. player.on('progress', function() {
  281. console.log('i = ' + i)
  282. if (i % 5 === 0) {
  283. if (this.playRecord == null) {
  284. return
  285. }
  286. this.playRecord.currentTime = player.video.currentTime
  287. submitPlayRecord(this.playRecord)
  288. .then(res => {
  289. }).catch(error => {
  290. console.error(error.message)
  291. })
  292. }
  293. i++
  294. })*/
  295. },
  296. initFlvPlayer(videoId, coverUrl, videoUrl) {
  297. new DPlayer({
  298. container: document.getElementById('dplayer'),
  299. video: {
  300. url: videoUrl,
  301. type: 'flv'
  302. },
  303. pluginOptions: {
  304. flv: {
  305. // refer to https://github.com/bilibili/flv.js/blob/master/docs/api.md#flvjscreateplayer
  306. mediaDataSource: {
  307. // mediaDataSource config
  308. },
  309. config: {
  310. // config
  311. }
  312. }
  313. }
  314. })
  315. },
  316. initHlsPlayer(videoId, coverUrl, videoUrl) {
  317. new DPlayer({
  318. container: document.querySelector('#dplayer'),
  319. lang: 'zh-cn',
  320. autoplay: false,
  321. screenshot: true,
  322. video: {
  323. pic: coverUrl,
  324. url: videoUrl,
  325. type: 'hls'
  326. },
  327. logo: '/logo.png',
  328. danmaku: {
  329. id: videoId,
  330. maximum: 10000,
  331. api: '//api.reghao.cn/api/media/danmaku/',
  332. token: 'bili',
  333. user: this.userPermission.userId,
  334. videoId: videoId,
  335. bottom: '15%',
  336. unlimited: true
  337. }
  338. })
  339. },
  340. initDashPlayer(videoId, coverUrl, videoUrl) {
  341. new DPlayer({
  342. container: document.getElementById('dplayer'),
  343. video: {
  344. url: videoUrl,
  345. type: 'dash'
  346. }
  347. })
  348. },
  349. gotoHomePage() {
  350. this.permissionDialog = false
  351. if (this.$route.path === '/') {
  352. return
  353. }
  354. this.$router.push('/')
  355. },
  356. gotoVipPage() {
  357. this.permissionDialog = false
  358. if (this.$route.path === '/vip/plan') {
  359. return
  360. }
  361. this.$router.push('/vip/plan')
  362. },
  363. submitAuthCode() {
  364. this.authCodeDialog = false
  365. console.log('发送视频认证码')
  366. console.log(this.videoProp.videoId)
  367. console.log(this.authCode)
  368. this.getVideoUrl(this.videoProp.videoId)
  369. },
  370. cancelSubmitAuthCode() {
  371. this.authCodeDialog = false
  372. if (this.$route.path === '/') {
  373. return
  374. }
  375. this.$router.push('/')
  376. }
  377. }
  378. }
  379. </script>
  380. <style>
  381. #dplayer {
  382. height: 500px;
  383. }
  384. </style>