实现音频的播放只需要使用 Audio 标签即可,但是由于一些安全策略会禁止载入文件,所以我们要关闭安全策略。

关闭安全策略

关闭掉 webSecurity ,这样就可以读取本地的音频文件了,记得重启 Electron。

  1. mainWindow = createMainWindow({
  2. width: 400,
  3. height: 560,
  4. frame: false,
  5. transparent: true,
  6. show: false,
  7. webPreferences: {
  8. webSecurity: false
  9. }
  10. })

播放页面

我们先实现功能,之后再美化界面,我们现在通过 remote 访问主进程的一些模块,来选取文件夹,对 Mp3 文件进行排序,通过监听 svelte 的 state 状态修改事件,来监视播放地址的修改,这里一定要加上文件协议 file:// 要不然会报错,这里没有做平台兼容,平台的路径少许不同。

  1. <Back/>
  2. <div>
  3. <button on:click="next()">next</button>
  4. <button on:click="prev()">prev</button>
  5. <button on:click="file()">file</button>
  6. </div>
  7. <script>
  8. import {
  9. ipcRenderer,
  10. remote
  11. } from "electron";
  12. const {
  13. dialog,
  14. app
  15. } = remote
  16. const {
  17. readdir
  18. } = remote.require('fs-extra')
  19. import {
  20. resolve
  21. } from 'path'
  22. export default {
  23. data() {
  24. return {
  25. currentSrc: '',
  26. index: 0,
  27. files: []
  28. };
  29. },
  30. components: {
  31. Back: '../components/Back.svelte'
  32. },
  33. oncreate() {
  34. this.player = new Audio()
  35. document.querySelector('#app').appendChild(this.player)
  36. this.player.onended = this.next // 播放完成下一首
  37. this.on('state', ({
  38. changed
  39. }) => {
  40. if (changed.currentSrc) {
  41. this.player.src = this.get().currentSrc
  42. this.play()
  43. }
  44. })
  45. },
  46. methods: {
  47. next() { // 下一曲
  48. const {
  49. index,
  50. files
  51. } = this.get()
  52. let i = index + 1
  53. if (i > files.length - 1) { // 边界守护
  54. i = files.length - 1
  55. }
  56. this.set({
  57. index: i,
  58. currentSrc: "file://" + files[i]
  59. })
  60. },
  61. prev() { // 上一曲
  62. const {
  63. index,
  64. files
  65. } = this.get()
  66. let i = index - 1
  67. if (i < 0) { // 边界守护
  68. i = 0
  69. }
  70. this.set({
  71. index: i,
  72. currentSrc: "file://" + files[i]
  73. })
  74. },
  75. play() { // 播放
  76. this.player.play()
  77. },
  78. pause() { // 暂停
  79. this.play.pause()
  80. },
  81. file() { // 选取文件
  82. dialog.showOpenDialog({
  83. title: '选择音乐目录',
  84. defaultPath: app.getPath('home'),
  85. properties: ['openDirectory']
  86. }, async(folders) => {
  87. if (folders.length > 0) {
  88. const folder = folders[0]
  89. let files = await readdir(folder)
  90. const compare = (a, b) => { // 比较字符串前面的数字
  91. let t1 = a.split('-')[0];
  92. let t2 = b.split('-');
  93. return parseInt(t1) - parseInt(t2)
  94. }
  95. files = files.sort(compare).map(file => resolve(folder, file)) // 文件排序
  96. this.set({
  97. files,
  98. currentSrc: "file://" + files[0]
  99. })
  100. }
  101. })
  102. }
  103. }
  104. };
  105. </script>