diff --git a/package.json b/package.json index a4346200c..4518aefbc 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "markdown-it-mathjax3": "^4.3.2", "moment": "^2.30.1", "monaco-editor": "^0.49.0", + "mpegts.js": "^1.7.3", "nanoid": "^5.0.7", "node-fetch": "^3.3.2", "node-json-db": "^2.3.0", diff --git a/src/renderer/src/utils/common/player/index.ts b/src/renderer/src/utils/common/player/index.ts index 6a06cec6c..b451897cd 100644 --- a/src/renderer/src/utils/common/player/index.ts +++ b/src/renderer/src/utils/common/player/index.ts @@ -36,7 +36,8 @@ * - 修复artplayer弹幕库5.1版本-参数对齐 * - 修复nplayer弹幕不滚动-BulletOption中type赋值错误 * - 修复dplayer弹幕控制不生效-弹幕开关控制逻辑误删 - * + * - 2024.6.3: + * - 支持mp3|m4a音频-使用MPEG-TS库 * * --- */ @@ -46,6 +47,9 @@ import { checkMediaType, checkLiveM3U8 } from '@/utils/tool'; let playerModulesCache: { [key: string]: any } = {}; const mapVideoTypeToPlayerType = (videoType: string): string | undefined => { + const audioTypes = ['mp3', 'm4a', 'wav', 'flac', 'aac', 'ogg', 'wma']; + if (audioTypes.includes(videoType)) return 'customMpegts'; + switch (videoType) { case 'mp4': return 'customMp4'; diff --git a/src/renderer/src/utils/common/player/playerModule/components/depend.ts b/src/renderer/src/utils/common/player/playerModule/components/depend.ts index ed3a532f3..28b5c58c9 100644 --- a/src/renderer/src/utils/common/player/playerModule/components/depend.ts +++ b/src/renderer/src/utils/common/player/playerModule/components/depend.ts @@ -1,4 +1,5 @@ // import dashjs from 'dashjs'; +import MpegTs from 'mpegts.js'; import flvjs from 'flv.js'; import Hls from 'hls.js'; import WebTorrent from './modules/webtorrent'; @@ -84,6 +85,22 @@ const publicStream = { return null; } }, + customMpegts: (video: HTMLVideoElement, url: string): any => { + if (MpegTs.isSupported()) { + const playerMpegts = MpegTs.createPlayer({ + type: 'mse', // could also be mpegts, m2ts, flv + isLive: false, + url, + }); + playerMpegts.attachMediaElement(video); + playerMpegts.load(); + playerMpegts.play(); + return playerMpegts; + } else { + console.log('mpegts is not supported.'); + return null; + } + }, }, switch: { customHls: (video: HTMLVideoElement, hls: any, url: string): Hls => { @@ -145,6 +162,18 @@ const publicStream = { }); return client; }, + customMpegts: (video: HTMLVideoElement, mpegts: any, url: string) => { + mpegts.destroy(); + const playerMpegts = MpegTs.createPlayer({ + type: 'mse', // could also be mpegts, m2ts, flv + isLive: false, + url, + }); + playerMpegts.attachMediaElement(video); + playerMpegts.load(); + playerMpegts.play(); + return playerMpegts; + }, }, destroy: { customHls: (player: any) => { @@ -164,6 +193,9 @@ const publicStream = { player.torrent.destroy(); delete player.torrent; }, + customMpegts: (player: any) => { + player.destroy(); + }, }, }; diff --git a/src/renderer/src/utils/tool.ts b/src/renderer/src/utils/tool.ts index 160ee4d02..7dd38eafb 100644 --- a/src/renderer/src/utils/tool.ts +++ b/src/renderer/src/utils/tool.ts @@ -98,10 +98,26 @@ const getHtml = async (url: string, method = 'GET', encode = 'UTF-8', headers = } }; +const supportedFormats: string[] = [ + 'mp4', + 'mkv', + 'flv', + 'm3u8', + 'avi', + 'magnet', + 'mpd', + 'mpd', + 'mp3', + 'm4a', + 'wav', + 'flac', + 'aac', + 'ogg', + 'wma', +]; + // 判断媒体类型 const checkMediaType = async (url: string): Promise => { - const supportedFormats: string[] = ['mp4', 'mkv', 'flv', 'm3u8', 'avi', 'magnet', 'mpd']; - if (url && (url.startsWith('http') || url.startsWith('magnet'))) { const fileType: any = supportedFormats.find((format) => url.includes(format)); if (fileType) { @@ -127,6 +143,7 @@ const getMeadiaType = async (url: string): Promise => { const supportedFormats: Record = { 'video/mp4': 'mp4', 'video/x-flv': 'flv', + 'video/ogg': 'ogx', 'application/vnd.apple.mpegurl': 'm3u8', 'application/x-mpegURL': 'm3u8', 'application/octet-stream': 'm3u8', @@ -136,6 +153,10 @@ const getMeadiaType = async (url: string): Promise => { 'video/quicktime': 'mov', 'video/x-ms-wmv': 'wmv', 'video/3gpp': '3gp', + 'audio/mpeg': 'mp3', + 'audio/wav': 'mav', + 'audio/aac': 'aac', + 'audio/ogg': 'oga', }; for (const format in supportedFormats) { @@ -338,6 +359,7 @@ const decodeHtml = (str: string) => { export { getConfig, getHtml, + supportedFormats, getMeadiaType, checkMediaType, checkUrlIpv6, diff --git a/yarn.lock b/yarn.lock index 09dfb9a1d..df2a75218 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3265,7 +3265,7 @@ es6-iterator@^2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promise@^4.2.4, es6-promise@^4.2.8: +es6-promise@^4.2.4, es6-promise@^4.2.5, es6-promise@^4.2.8: version "4.2.8" resolved "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== @@ -5275,6 +5275,14 @@ monaco-editor@^0.49.0: resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.49.0.tgz#4e80e9859feb2c421def3cef194d12d822606472" integrity sha512-2I8/T3X/hLxB2oPHgqcNYUVdA/ZEFShT7IAujifIPMfKkNbLOqY8XCoyHCXrsdjb36dW9MwoTwBCFpXKMwNwaQ== +mpegts.js@^1.7.3: + version "1.7.3" + resolved "https://registry.npmmirror.com/mpegts.js/-/mpegts.js-1.7.3.tgz#a422ed501d778fa86f9eef98d71fd62fc013f262" + integrity sha512-kqZ1C1IsbAQN72cK8vMrzKeM7hwrwSBbFAwVAc7PPweOeoZxCANrc7fAVDKMfYUzxdNkMTnec9tVmlxmKZB0TQ== + dependencies: + es6-promise "^4.2.5" + webworkify-webpack "^2.1.5" + mrmime@^2.0.0: version "2.0.0" resolved "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4"