fix : 修复hls直播转mp4缺少的一个参数

This commit is contained in:
shuohigh@gmail.com 2025-06-18 16:57:15 +08:00
parent 0f66ac03c2
commit 1920b4bd9d
3 changed files with 30 additions and 14 deletions

View File

@ -9,6 +9,7 @@ from loguru import logger
import httpx
from fastapi import APIRouter, UploadFile, Header, HTTPException, Depends
from pydantic import BaseModel, Field
from pydantic import computed_field
from starlette import status
from starlette.responses import JSONResponse
@ -34,8 +35,18 @@ class BundleHeaders(BaseModel):
x_baggage: str = Field(description="Sentry Transaction baggage", default=None)
class GoogleAuthHeaders(BaseModel):
Authorization: str = Field(description="Google Auth Bearer Token")
@computed_field(description="Google Auth Token")
@property
def auth_token(self) -> str:
return self.Authorization[len("Bearer "):]
@router.post("/upload",
summary="上传文件到Google File",
summary="上传文件到Google AI Studio提供的File API, 将被VertexAI新规范替代统一使用Google CloudStorage存储",
deprecated=True,
description="上传文件到Google File, 换取Google File URI, 不同Google API Key之间的URI不互通, 最多可为每个项目存储 20 GB 的文件,每个文件的大小上限为 2 GB。文件会存储 48 小时")
async def upload_file_multipart(file: UploadFile,
headers: Annotated[GoogleAPIKeyHeaders, Header()]):
@ -80,6 +91,10 @@ async def upload_file_multipart(file: UploadFile,
return JSONResponse(content=upload_response.json(), status_code=upload_response.status_code)
@router.post("/vertex-ai/upload", summary="上传文件到Vertex AI可访问的Google cloud storage", )
async def upload_file(file: UploadFile, headers: Annotated[GoogleAuthHeaders, Header()]):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
@router.get("/status", summary="获取已上传文件的处理状态")
async def uploaded_file_status(filename: str,
headers: Annotated[GoogleAPIKeyHeaders, Header()]):

View File

@ -1,4 +1,4 @@
from typing import Union, Dict, Any
from typing import Union, Dict, Any, BinaryIO
import backoff
import httpx
@ -126,3 +126,7 @@ class GoogleAuthUtils:
data=params)
response.raise_for_status()
return GoogleAuthUtils.GoogleAuthResponse.model_validate_json(response.text)
# @staticmethod
# async def google_upload_file(file_stream: BinaryIO, google_api_key: str, bucket_name: str):
#

View File

@ -455,7 +455,7 @@ class VideoUtils:
duration = seek_tail - seek_head
logger.info(f"Only using {seek_head}s --> {seek_tail}s = {duration}s")
local_m3u8_path, temp_dir, diff = await VideoUtils.convert_m3u8_to_local_source(media_path, head=seek_head,
tail=seek_tail)
tail=seek_tail)
logger.info(f"local_playlist: {local_m3u8_path}")
for segment in media_markers:
@ -557,13 +557,17 @@ class VideoUtils:
@staticmethod
async def convert_m3u8_to_local_source(media_stream_url: str,
head: Optional[float] = None,
tail: Optional[float] = None) -> tuple[str, str, TimeDelta]:
head: float = 0,
tail: float = 86400, # 使用24H时长替代♾
temp_dir: str = None) -> tuple[str, str, TimeDelta]:
"""
转换m3u8为本地来源
"""
# 创建临时目录存储TS片段
temp_dir = tempfile.mkdtemp()
if temp_dir:
os.makedirs(temp_dir, exist_ok=True)
else:
temp_dir = tempfile.mkdtemp()
from m3u8 import SegmentList, Segment
try:
# 1. 下载m3u8文件
@ -578,10 +582,6 @@ class VideoUtils:
max_head = origin_time + timedelta(seconds=tail)
logger.info(f"min: {min_head}, max: {max_head}")
for segment in playlist.segments:
if not head:
head = 0
if not tail:
tail = 86400 # 使用24H时长替代♾
if min_head - timedelta(seconds=segment.duration) <= segment.current_program_date_time <= max_head:
logger.info(f"duration: {segment.duration}, head: {segment.current_program_date_time}")
duration += segment.duration
@ -600,13 +600,10 @@ class VideoUtils:
playlist.is_endlist = True
for url in ts_urls:
tasks.append(VideoUtils.async_download_file(url.absolute_uri, f"{temp_dir}/{url.uri}"))
await asyncio.gather(*tasks)
# 4. 修改m3u8文件指向本地TS片段
local_m3u8_path = os.path.join(temp_dir, "local.m3u8")
playlist.dump(local_m3u8_path)
return local_m3u8_path, temp_dir, diff
except Exception as e:
logger.exception(e)
@ -631,7 +628,7 @@ class VideoUtils:
os.makedirs(os.path.dirname(output_path), exist_ok=True)
try:
local_m3u8_path, temp_dir = await VideoUtils.convert_m3u8_to_local_source(media_stream_url=media_stream_url)
local_m3u8_path, temp_dir, diff = await VideoUtils.convert_m3u8_to_local_source(media_stream_url=media_stream_url)
# 使用ffmpeg合并TS片段
ffmpeg_cmd = VideoUtils.async_ffmpeg_init()
ffmpeg_cmd.input(local_m3u8_path,