video-url-helper.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. * 视频播放地址处理工具函数(TypeScript版本)
  3. * 用于前端处理HTTP资源在HTTPS网站中的访问问题
  4. *
  5. * 使用方法:
  6. * import { getVideoPlayUrl, processVideoList } from './video-url-helper'
  7. *
  8. * const playUrl = getVideoPlayUrl('http://example.com/video.m3u8')
  9. */
  10. export interface VideoItem {
  11. id: number
  12. title: string
  13. m3u8: string
  14. image?: string
  15. [key: string]: any
  16. }
  17. export interface VideoUrlOptions {
  18. baseUrl?: string
  19. forceProxy?: boolean
  20. }
  21. /**
  22. * 获取视频播放地址(自动处理HTTP资源)
  23. * @param m3u8Url 后端返回的m3u8地址
  24. * @param options 配置选项
  25. * @returns 处理后的播放地址
  26. */
  27. export function getVideoPlayUrl(
  28. m3u8Url: string,
  29. options: VideoUrlOptions = {}
  30. ): string {
  31. if (!m3u8Url || typeof m3u8Url !== 'string') {
  32. return m3u8Url
  33. }
  34. try {
  35. const url = new URL(m3u8Url)
  36. const baseUrl = options.baseUrl || window.location.origin
  37. // 强制使用代理
  38. if (options.forceProxy) {
  39. const path = url.pathname + url.search + url.hash
  40. return `${baseUrl}/api/proxy/m3u8${path}`
  41. }
  42. // HTTPS直接使用
  43. if (url.protocol === 'https:') {
  44. return m3u8Url
  45. }
  46. // HTTP转换为代理地址
  47. if (url.protocol === 'http:') {
  48. const path = url.pathname + url.search + url.hash
  49. return `${baseUrl}/api/proxy/m3u8${path}`
  50. }
  51. // 其他情况,直接返回
  52. return m3u8Url
  53. } catch (error) {
  54. console.warn('处理视频地址失败:', error, m3u8Url)
  55. return m3u8Url
  56. }
  57. }
  58. /**
  59. * 批量处理视频列表的播放地址
  60. * @param videos 视频列表数组
  61. * @param options 配置选项
  62. * @returns 处理后的视频列表
  63. */
  64. export function processVideoList<T extends VideoItem>(
  65. videos: T[],
  66. options: VideoUrlOptions = {}
  67. ): T[] {
  68. if (!Array.isArray(videos)) {
  69. return videos
  70. }
  71. return videos.map(video => {
  72. if (video.m3u8) {
  73. return {
  74. ...video,
  75. m3u8: getVideoPlayUrl(video.m3u8, options)
  76. }
  77. }
  78. return video
  79. })
  80. }
  81. /**
  82. * 检查地址是否需要代理
  83. * @param m3u8Url m3u8地址
  84. * @returns 是否需要代理
  85. */
  86. export function needsProxy(m3u8Url: string): boolean {
  87. if (!m3u8Url || typeof m3u8Url !== 'string') {
  88. return false
  89. }
  90. try {
  91. const url = new URL(m3u8Url)
  92. return url.protocol === 'http:'
  93. } catch {
  94. return false
  95. }
  96. }
  97. /**
  98. * 默认导出(方便使用)
  99. */
  100. export default {
  101. getVideoPlayUrl,
  102. processVideoList,
  103. needsProxy
  104. }