test-video-real-url.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /**
  2. * 测试获取视频真实播放地址功能
  3. * 使用方法: ts-node test-video-real-url.ts
  4. * 或者: npx ts-node test-video-real-url.ts
  5. */
  6. import axios from 'axios'
  7. import dotenv from 'dotenv'
  8. // 加载环境变量
  9. dotenv.config()
  10. // 配置
  11. const BASE_URL = process.env.BASE_URL || 'http://localhost:3010'
  12. const TEST_VIDEO_ID = 38230
  13. // 颜色输出工具
  14. const colors = {
  15. reset: '\x1b[0m',
  16. bright: '\x1b[1m',
  17. green: '\x1b[32m',
  18. red: '\x1b[31m',
  19. yellow: '\x1b[33m',
  20. blue: '\x1b[34m',
  21. cyan: '\x1b[36m'
  22. }
  23. function log(message: string, color: string = colors.reset) {
  24. console.log(`${color}${message}${colors.reset}`)
  25. }
  26. function logSuccess(message: string) {
  27. log(`✅ ${message}`, colors.green)
  28. }
  29. function logError(message: string) {
  30. log(`❌ ${message}`, colors.red)
  31. }
  32. function logInfo(message: string) {
  33. log(`ℹ️ ${message}`, colors.blue)
  34. }
  35. function logWarning(message: string) {
  36. log(`⚠️ ${message}`, colors.yellow)
  37. }
  38. /**
  39. * 测试获取视频真实播放地址
  40. */
  41. async function testGetVideoRealUrl(videoId: number) {
  42. try {
  43. logInfo(`\n开始测试获取视频真实播放地址 (视频ID: ${videoId})...`)
  44. const url = `${BASE_URL}/api/video/real-url?id=${videoId}`
  45. log(`请求URL: ${url}`, colors.cyan)
  46. const response = await axios.get(url, {
  47. timeout: 10000,
  48. validateStatus: () => true // 接受所有状态码
  49. })
  50. log(`\n响应状态码: ${response.status}`, colors.cyan)
  51. log(`响应数据:`, colors.cyan)
  52. console.log(JSON.stringify(response.data, null, 2))
  53. if (response.status === 200 && response.data.code === 1) {
  54. logSuccess('获取视频播放地址成功!')
  55. log(`\n视频ID: ${response.data.data.id}`)
  56. if (response.data.data.originalUrl) {
  57. log(`\n原始获取地址:`, colors.green)
  58. log(`${response.data.data.originalUrl}`, colors.bright)
  59. }
  60. if (response.data.data.proxyUrl) {
  61. log(`\n代理地址:`, colors.yellow)
  62. log(`${response.data.data.proxyUrl}`, colors.bright)
  63. }
  64. if (response.data.data.realUrl) {
  65. log(`\n真实地址(替换过域名):`, colors.cyan)
  66. log(`${response.data.data.realUrl}`, colors.bright)
  67. }
  68. if (response.data.data.bestUrl) {
  69. log(`\n最佳播放地址:`, colors.bright + colors.green)
  70. log(`${response.data.data.bestUrl}`, colors.bright)
  71. }
  72. return response.data.data
  73. } else {
  74. logError(`获取失败: ${response.data.msg || '未知错误'}`)
  75. return null
  76. }
  77. } catch (error: any) {
  78. if (axios.isAxiosError(error)) {
  79. if (error.response) {
  80. logError(`请求失败: ${error.response.status} ${error.response.statusText}`)
  81. logError(`错误信息: ${JSON.stringify(error.response.data, null, 2)}`)
  82. } else if (error.request) {
  83. logError('请求已发送但没有收到响应')
  84. logError(`请确保服务器正在运行: ${BASE_URL}`)
  85. } else {
  86. logError(`请求配置错误: ${error.message}`)
  87. }
  88. } else {
  89. logError(`未知错误: ${error.message || String(error)}`)
  90. }
  91. return null
  92. }
  93. }
  94. /**
  95. * 测试获取视频详情(对比用)
  96. */
  97. async function testGetVideoDetail(videoId: number) {
  98. try {
  99. logInfo(`\n开始测试获取视频详情 (视频ID: ${videoId})...`)
  100. const url = `${BASE_URL}/api/video/detail?id=${videoId}`
  101. log(`请求URL: ${url}`, colors.cyan)
  102. const response = await axios.get(url, {
  103. timeout: 10000,
  104. validateStatus: () => true
  105. })
  106. log(`\n响应状态码: ${response.status}`, colors.cyan)
  107. if (response.status === 200 && response.data.code === 1) {
  108. logSuccess('获取视频详情成功!')
  109. log(`\n视频ID: ${response.data.data.id}`)
  110. log(`视频标题: ${response.data.data.title}`)
  111. log(`播放地址(代理后): ${response.data.data.m3u8}`, colors.yellow)
  112. return response.data.data.m3u8
  113. } else {
  114. logError(`获取失败: ${response.data.msg || '未知错误'}`)
  115. return null
  116. }
  117. } catch (error: any) {
  118. if (axios.isAxiosError(error)) {
  119. if (error.response) {
  120. logError(`请求失败: ${error.response.status} ${error.response.statusText}`)
  121. } else if (error.request) {
  122. logError('请求已发送但没有收到响应')
  123. } else {
  124. logError(`请求配置错误: ${error.message}`)
  125. }
  126. } else {
  127. logError(`未知错误: ${error.message || String(error)}`)
  128. }
  129. return null
  130. }
  131. }
  132. /**
  133. * 对比三个地址
  134. */
  135. function compareUrls(urlData: { originalUrl?: string | null; proxyUrl?: string | null; realUrl?: string | null; bestUrl?: string | null } | null) {
  136. if (!urlData) {
  137. return
  138. }
  139. log(`\n${'='.repeat(60)}`, colors.cyan)
  140. log('地址对比:', colors.bright)
  141. log(`${'='.repeat(60)}`, colors.cyan)
  142. if (urlData.originalUrl) {
  143. log(`\n原始获取地址:`, colors.green)
  144. log(`${urlData.originalUrl}`, colors.bright)
  145. }
  146. if (urlData.proxyUrl) {
  147. log(`\n代理播放地址:`, colors.yellow)
  148. log(`${urlData.proxyUrl}`, colors.bright)
  149. }
  150. if (urlData.realUrl) {
  151. log(`\n真实播放地址(替换过域名):`, colors.cyan)
  152. log(`${urlData.realUrl}`, colors.bright)
  153. }
  154. if (urlData.bestUrl) {
  155. log(`\n最佳播放地址:`, colors.bright + colors.green)
  156. log(`${urlData.bestUrl}`, colors.bright)
  157. }
  158. // 检查地址是否不同
  159. if (urlData.originalUrl && urlData.realUrl && urlData.originalUrl !== urlData.realUrl) {
  160. logSuccess('\n✓ 真实地址已替换域名(与原始地址不同)')
  161. } else if (urlData.originalUrl && urlData.realUrl) {
  162. logWarning('\n⚠ 真实地址未替换域名(与原始地址相同,可能未配置 video_source)')
  163. }
  164. if (urlData.originalUrl && urlData.proxyUrl && urlData.originalUrl !== urlData.proxyUrl) {
  165. logSuccess('✓ 代理地址已转换(与原始地址不同)')
  166. } else if (urlData.originalUrl && urlData.proxyUrl) {
  167. logWarning('⚠ 代理地址未转换(与原始地址相同)')
  168. }
  169. if (urlData.bestUrl) {
  170. try {
  171. const bestUrlObj = new URL(urlData.bestUrl)
  172. if (bestUrlObj.protocol === 'https:') {
  173. logSuccess('✓ 最佳播放地址使用HTTPS,无需代理,性能最佳')
  174. } else if (bestUrlObj.protocol === 'http:') {
  175. logWarning('⚠ 最佳播放地址使用HTTP代理,可能影响性能')
  176. }
  177. } catch (e) {
  178. // URL解析失败,忽略
  179. }
  180. }
  181. }
  182. /**
  183. * 主测试函数
  184. */
  185. async function main() {
  186. log(`\n${'='.repeat(60)}`, colors.bright)
  187. log('视频真实播放地址测试', colors.bright)
  188. log(`${'='.repeat(60)}`, colors.bright)
  189. log(`\n测试配置:`, colors.cyan)
  190. log(`- 服务器地址: ${BASE_URL}`)
  191. log(`- 测试视频ID: ${TEST_VIDEO_ID}`)
  192. // 测试1: 获取完整地址信息(原始地址、代理地址、真实地址)
  193. const urlData = await testGetVideoRealUrl(TEST_VIDEO_ID)
  194. // 测试2: 获取视频详情(包含代理地址)
  195. const proxyUrl = await testGetVideoDetail(TEST_VIDEO_ID)
  196. // 对比地址
  197. compareUrls(urlData)
  198. log(`\n${'='.repeat(60)}`, colors.bright)
  199. log('测试完成', colors.bright)
  200. log(`${'='.repeat(60)}`, colors.bright)
  201. }
  202. // 运行测试
  203. main().catch(error => {
  204. logError(`\n测试执行失败: ${error.message}`)
  205. console.error(error)
  206. process.exit(1)
  207. })