|
3 | 3 | import shutil
|
4 | 4 |
|
5 | 5 | from fastapi import Request, Depends, Path, BackgroundTasks, UploadFile
|
6 |
| -from fastapi.responses import FileResponse |
| 6 | +from fastapi.responses import FileResponse, StreamingResponse |
7 | 7 | from fastapi.params import File
|
8 | 8 | from loguru import logger
|
9 | 9 |
|
@@ -137,7 +137,37 @@ def upload_bgm_file(request: Request, file: UploadFile = File(...)):
|
137 | 137 | async def stream_video(request: Request, file_path: str):
|
138 | 138 | tasks_dir = utils.task_dir()
|
139 | 139 | video_path = os.path.join(tasks_dir, file_path)
|
140 |
| - if os.path.isfile(video_path): |
141 |
| - return FileResponse(video_path, media_type="video/mp4", filename=file_path) |
142 |
| - else: |
143 |
| - return {"message": "File not found."} |
| 140 | + range_header = request.headers.get('Range') |
| 141 | + video_size = os.path.getsize(video_path) |
| 142 | + start, end = 0, video_size - 1 |
| 143 | + |
| 144 | + length = video_size |
| 145 | + if range_header: |
| 146 | + range_ = range_header.split('bytes=')[1] |
| 147 | + start, end = [int(part) if part else None for part in range_.split('-')] |
| 148 | + if start is None: |
| 149 | + start = video_size - end |
| 150 | + end = video_size - 1 |
| 151 | + if end is None: |
| 152 | + end = video_size - 1 |
| 153 | + length = end - start + 1 |
| 154 | + |
| 155 | + def file_iterator(file_path, offset=0, bytes_to_read=None): |
| 156 | + with open(file_path, 'rb') as f: |
| 157 | + f.seek(offset, os.SEEK_SET) |
| 158 | + remaining = bytes_to_read or video_size |
| 159 | + while remaining > 0: |
| 160 | + bytes_to_read = min(4096, remaining) |
| 161 | + data = f.read(bytes_to_read) |
| 162 | + if not data: |
| 163 | + break |
| 164 | + remaining -= len(data) |
| 165 | + yield data |
| 166 | + |
| 167 | + response = StreamingResponse(file_iterator(video_path, start, length), media_type='video/mp4') |
| 168 | + response.headers['Content-Range'] = f'bytes {start}-{end}/{video_size}' |
| 169 | + response.headers['Accept-Ranges'] = 'bytes' |
| 170 | + response.headers['Content-Length'] = str(length) |
| 171 | + response.status_code = 206 # Partial Content |
| 172 | + |
| 173 | + return response |
0 commit comments