|
1 | 1 | import {base64Decode} from '../libs_drpy/crypto-util.js'; |
2 | 2 | import '../utils/random-http-ua.js' |
3 | 3 | import {keysToLowerCase} from '../utils/utils.js'; |
| 4 | +import {ENV} from "../utils/env.js"; |
| 5 | +import chunkStream, {testSupport} from '../utils/chunk.js'; |
4 | 6 | import http from 'http'; |
5 | 7 | import https from 'https'; |
6 | 8 | import axios from 'axios'; |
@@ -36,80 +38,30 @@ export default (fastify, options, done) => { |
36 | 38 | : {}; |
37 | 39 |
|
38 | 40 | // Call the proxy function, passing the decoded URL and headers |
39 | | - // return await proxyStreamMedia(decodedUrl, decodedHeader, reply); |
40 | | - return await proxyStreamMediaMulti(decodedUrl, decodedHeader, request, reply, thread, size, randUa); |
| 41 | + // return await proxyStreamMediaMulti(decodedUrl, decodedHeader, request, reply, thread, size, randUa); |
| 42 | + // return await chunkStream(request, reply, decodedUrl, ids[1], Object.assign({Cookie: cookie}, baseHeader)); |
| 43 | + if (ENV.get('play_proxy_mode', '1') !== '2') { // 2磁盘加速 其他都是内存加速 |
| 44 | + console.log('[mediaProxy] proxyStreamMediaMulti 内存加速:chunkSize:', sizeToBytes(size)); |
| 45 | + return await proxyStreamMediaMulti(decodedUrl, decodedHeader, request, reply, thread, size, randUa); |
| 46 | + } else { |
| 47 | + console.log('[mediaProxy] chunkStream 磁盘加速 chunkSize:', sizeToBytes('256K')); |
| 48 | + return await chunkStream(request, reply, decodedUrl, null, decodedHeader, |
| 49 | + Object.assign({chunkSize: 1024 * 256, poolSize: 5, timeout: 1000 * 10}, { |
| 50 | + // chunkSize: sizeToBytes(size), |
| 51 | + poolSize: thread |
| 52 | + }) |
| 53 | + ); |
| 54 | + } |
41 | 55 | } catch (error) { |
42 | | - fastify.log.error(error); |
| 56 | + // fastify.log.error(error); |
| 57 | + fastify.log.error(error.message); |
43 | 58 | reply.code(500).send({error: error.message}); |
44 | 59 | } |
45 | 60 | }); |
46 | 61 |
|
47 | 62 | done(); |
48 | 63 | }; |
49 | 64 |
|
50 | | -// 媒体文件 流式代理,单线程管道方式发送数据,且存在bug,暂不使用 |
51 | | -function proxyStreamMedia(videoUrl, headers, reply) { |
52 | | - console.log(`进入了流式代理: ${videoUrl} | headers: ${JSON.stringify(headers)}`); |
53 | | - |
54 | | - const protocol = videoUrl.startsWith('https') ? https : http; |
55 | | - const agent = videoUrl.startsWith('https') ? httpsAgent : httpAgent; |
56 | | - |
57 | | - // 发起请求 |
58 | | - const proxyRequest = protocol.request(videoUrl, {headers, agent}, (videoResponse) => { |
59 | | - console.log('videoResponse.statusCode:', videoResponse.statusCode); |
60 | | - console.log('videoResponse.headers:', videoResponse.headers); |
61 | | - |
62 | | - if (videoResponse.statusCode === 200 || videoResponse.statusCode === 206) { |
63 | | - const resp_headers = { |
64 | | - 'Content-Type': videoResponse.headers['content-type'] || 'application/octet-stream', |
65 | | - 'Content-Length': videoResponse.headers['content-length'], |
66 | | - ...(videoResponse.headers['content-range'] ? {'Content-Range': videoResponse.headers['content-range']} : {}), |
67 | | - }; |
68 | | - console.log('Response headers:', resp_headers); |
69 | | - reply.headers(resp_headers).status(videoResponse.statusCode); |
70 | | - |
71 | | - // 将响应流直接管道传输给客户端 |
72 | | - videoResponse.pipe(reply.raw); |
73 | | - |
74 | | - videoResponse.on('data', (chunk) => { |
75 | | - console.log('Data chunk received, size:', chunk.length); |
76 | | - }); |
77 | | - |
78 | | - videoResponse.on('end', () => { |
79 | | - console.log('Video data transmission complete.'); |
80 | | - }); |
81 | | - |
82 | | - videoResponse.on('error', (err) => { |
83 | | - console.error('Error during video response:', err.message); |
84 | | - reply.code(500).send({error: 'Error streaming video', details: err.message}); |
85 | | - }); |
86 | | - |
87 | | - reply.raw.on('finish', () => { |
88 | | - console.log('Data fully sent to client'); |
89 | | - }); |
90 | | - |
91 | | - // 监听关闭事件,销毁视频响应流 |
92 | | - reply.raw.on('close', () => { |
93 | | - console.log('Response stream closed.'); |
94 | | - videoResponse.destroy(); |
95 | | - }); |
96 | | - } else { |
97 | | - console.error(`Unexpected status code: ${videoResponse.statusCode}`); |
98 | | - reply.code(videoResponse.statusCode).send({error: 'Failed to fetch video'}); |
99 | | - } |
100 | | - }); |
101 | | - |
102 | | - // 监听错误事件 |
103 | | - proxyRequest.on('error', (err) => { |
104 | | - console.error('Proxy request error:', err.message); |
105 | | - reply.code(500).send({error: 'Error fetching video', details: err.message}); |
106 | | - }); |
107 | | - |
108 | | - // 必须调用 .end() 才能发送请求 |
109 | | - proxyRequest.end(); |
110 | | -} |
111 | | - |
112 | | - |
113 | 65 | // Helper function for range-based chunk downloading |
114 | 66 | async function fetchStream(url, userHeaders, start, end, randUa) { |
115 | 67 | const headers = keysToLowerCase({ |
@@ -315,7 +267,6 @@ async function proxyStreamMediaMulti(mediaUrl, reqHeaders, request, reply, threa |
315 | 267 | } |
316 | 268 | } |
317 | 269 |
|
318 | | - |
319 | 270 | // Helper function to convert size string (e.g., '128K', '1M') to bytes |
320 | 271 | function sizeToBytes(size) { |
321 | 272 | const sizeMap = { |
|
0 commit comments