关于vue-dplayer的弹幕功能使用问题以及解决方案

青旬

vue-dplayer的安装

npm install vue-dplayer --save

在使用vue-dplayer开发视频播放器过程中,关于弹幕功能的问题需要解释一下

  1. <template>
  2. <div id="test">
  3. <vue-dplayer id="dplayer" ref="dplayerRef" class="dplayer" :options="options"></vue-dplayer>
  4. </div>
  5. </template>
  6. <script>
  7. import VueDPlayer from 'vue-dplayer'
  8. export default {
  9. components: {
  10. VueDPlayer
  11. },
  12. data() {
  13. return {
  14. options: {
  15. lang: "zh-cn",
  16. preload: 'auto',
  17. video: {
  18. type: 'auto',
  19. url: 'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4'
  20. }
  21. }
  22. }
  23. },
  24. created() {
  25. },
  26. methods: {}
  27. }
  28. </script>
  29. <style>
  30. #test {
  31. }
  32. .dplayer {
  33. height: 400px;
  34. width: 800px;
  35. }
  36. </style>

这是一个非常干净,只有基础播放器功能的代码

前端展示效果如下

然后我们来看一下 DPlayer api 的接口文档地址https://dplayer.diygod.dev/zh/guide.html

所以options的内容被改为

  1. options: {
  2. lang: "zh-cn",
  3. preload: 'auto',
  4. video: {
  5. type: 'auto',
  6. url: 'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4'
  7. },
  8. danmaku: true,
  9. apiBackend: {
  10. read (options) {
  11. console.log('Pretend to connect WebSocket');
  12. options.success([]);
  13. },
  14. send (options) {
  15. console.log('Pretend to send danmaku via WebSocket', options.data);
  16. options.success();
  17. },
  18. }
  19. }

结果前端报错:

TypeError: options.success is not a function
[Vue warn]: Error in mounted hook: "TypeError: options.success is not a function"

意思是没有options.success这个方法

怎么会没有呢,都是按照文档的步骤来的呢

输出这两条试试

read: undefinedv2/?id=undefined

send: undefinedv2/
其实看到这我就知道了,如果把官方给的danmaku.id 和 danmaku.api 加上去的话就能拼成一个完整的url
可就算这样也不能使用options.success()这个方法,没办法只能看源代码

DPlayer/blob/master/demo/demo.js
从这段demo.js代码中可以找到https://s-sh-17-dplayercdn.oss.dogecdn.com/1678963.json这个示例数据,大概是长这样子的

  1. {
  2. "code": 0,
  3. "data": [
  4. [
  5. 230.523,
  6. 0,
  7. 16777215,
  8. "618c713c",
  9. "键盘妹子挺好看?"
  10. ],
  11. [
  12. 25.837,
  13. 0,
  14. 16777215,
  15. "6b2884ac",
  16. "Goose house炒鸡棒!!! 银之匙种草他们组合"
  17. ],
  18. [
  19. 235.243,
  20. 1,
  21. 16707842,
  22. "929815d3",
  23. "刚才说比其他翻唱都好听的你是认真的么,这。就是原唱"
  24. ],
  25. ...
  26. ]
  27. }

为什么是长这个样子的呢?我后面再讲,咱们先继续往下看

找到被作者注释掉的read 和 send方法,看看作者是怎么写的

原来传了不止一条数据,我就奇怪了为什么options.success()这方法找不到

我们在read方法中用  console .log('callback: ' + callback); 看看callback有什么

  1. callback: function (s, r) {
  2. if (++a, s)
  3. s.response ? n.options.error(s.response.msg) : n.options.error("Request was unsuccessful: " + s.status), i[o] = [];
  4. else {
  5. var l = ["right", "top", "bottom"];
  6. i[o] = r ? r.map(function (e) {
  7. return {
  8. time: e[0],
  9. type: l[e[1]],
  10. color: e[2],
  11. author: e[3],
  12. text: e[4]
  13. };
  14. }) : [];
  15. }
  16. if (a === e.length)
  17. return t(i);
  18. }

拿 [230.523, 0, 16777215, "618c713c", "键盘妹子挺好看?"] 这条数据来看的话,相当于

  1. {
  2. time: 230.523,
  3. type: "right",
  4. color: "#fff",
  5. author: "618c713c",
  6. text: "键盘妹子挺好看?"
  7. }

其中color需要将10进制转成16进制

文档中有给出danmaku.id danmaku.api这两条数据给我们使用,但是实际上作者会给你的api上加条非常诡异的后缀 v2/?id=,控制台能看到他调用api接口,但是弹幕就是加载不上去。

解决办法

我们不能使用作者提供的danmaku.id danmaku.api,需要自己覆写read send方法

  1. import {getDanmuList, addDanmu} from '@/api/video/videoDanmu'
  2. options: {
  3. lang: "zh-cn",
  4. preload: 'auto',
  5. video: {
  6. type: 'auto',
  7. url: 'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4'
  8. },
  9. danmaku: true,
  10. apiBackend: {
  11. send: (endpoint, danmakuData, callback) => {
  12. const danmu = {
  13. color: danmakuData.color,
  14. type: danmakuData.type === 'right' ? 0 : danmakuData.type === 'top' ? 1 : 2,
  15. text: danmakuData.text,
  16. time: danmakuData.time
  17. }
  18. addDanmu(danmu).then((response) => {
  19. this.$notify({
  20. title: '弹幕发送成功',
  21. message: danmu.text,
  22. type: 'success'
  23. });
  24. callback();
  25. }).catch((error) => {
  26. this.$notify.error({
  27. title: '失败',
  28. message: '弹幕发送失败 ' + error,
  29. });
  30. })
  31. },
  32. read: (endpoint, callback) => {
  33. getDanmuList(this.video.id).then((response) => {
  34. if (!response || response.code !== 0) {
  35. endpoint.error && endpoint.error(response && response.msg);
  36. return;
  37. }
  38. callback('', response.data);
  39. }).catch((e) => {
  40. console.error(e);
  41. endpoint.error && endpoint.error();
  42. });
  43. }
  44. }
  45. }

send方法中的danmakuData参数就是用户填写的弹幕信息,大概就是这样的json数据

  1. {
  2. "color": "#fff",
  3. "type": 0,
  4. "text": "123",
  5. "time": 0
  6. }

可以选择自己重新包装一层,看你要设计成什么样的 数据结构 。最后一定要调用callback()方法将发送弹幕的对话框关闭掉

read方法要注意一下,因为作者设计的接口数据格式非常逆天,在调用了自己的后端接口获取到弹幕数据之后,一定要改成这样格式的数据
 

  1. [
  2. [
  3. "5.713021",
  4. 0,
  5. "#fff",
  6. "c3cad6e5",
  7. "嗨哈嗨"
  8. ],
  9. [
  10. "2.572623",
  11. 0,
  12. "#fff",
  13. "c3cad6e5",
  14. "嗨嗨嗨"
  15. ],
  16. ...
  17. ]

 然后像这样子callback('', response. data )塞到播放器里面就可以发送弹幕了


这是我的个人博客,里面有很多经典案例,感兴趣的可以一起来学习  blog.qxbase.com