🐛 修复 video streaming

This commit is contained in:
xtaodada 2023-08-18 09:55:15 +08:00
parent ffcbce2edb
commit 906684fb54
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659

View File

@ -14,6 +14,7 @@ from defs.request import cache_dir
from init import bot, logger from init import bot, logger
FFMPEG_PATH = "ffmpeg" FFMPEG_PATH = "ffmpeg"
FFPROBE_PATH = "ffprobe"
LOCK = Lock() LOCK = Lock()
EDIT_TEMP_SECONDS = 10.0 EDIT_TEMP_SECONDS = 10.0
MESSAGE_MAP: Dict[int, float] = {} MESSAGE_MAP: Dict[int, float] = {}
@ -178,6 +179,41 @@ async def download_url(url: str, out: str, m: Message, start: str):
await f.write(chunk) await f.write(chunk)
async def get_video_duration(path: str) -> float:
"""获取视频时长"""
video_duration, code = await execute(
f"{FFPROBE_PATH} -v error -select_streams v:0 -show_entries format=duration "
f"-of default=noprint_wrappers=1:nokey=1 {path}"
)
if code != 0:
raise FFmpegError("视频时长获取失败")
return round(float(video_duration))
async def get_video_height_width(path: str) -> Tuple[int, int]:
"""获取视频高度和宽度"""
result, code = await execute(
f"{FFPROBE_PATH} -v error -select_streams v:0 -show_entries stream=width,height "
f"-of csv=s=x:p=0 {path}"
)
if code != 0:
raise FFmpegError("视频宽高度获取失败")
video_width, video_height = result.split("x")
return int(video_height), int(video_width)
async def take_screenshot(path: str, output_path: str, video_duration: float):
"""随机一张视频截图"""
_, code = await execute(
f"{FFMPEG_PATH} -v error -i {path} -vcodec mjpeg -vframes 1 -an -f rawvideo "
f"-ss {int(video_duration / 2)} "
f"-vf scale='if(gt(iw,ih),90,trunc(oh*a/2)*2)':'if(gt(iw,ih),trunc(ow/a/2)*2,90)' "
f"{output_path}"
)
if code != 0:
raise FFmpegError("视频提取帧截图失败")
async def go_download(v: Video, p_num: int, m: Message): async def go_download(v: Video, p_num: int, m: Message):
video_path = cache_dir / f"{v.get_aid()}_{p_num}.mp4" video_path = cache_dir / f"{v.get_aid()}_{p_num}.mp4"
safe_remove(video_path) safe_remove(video_path)
@ -210,7 +246,7 @@ async def go_download(v: Video, p_num: int, m: Message):
logger.info("Merging video and audio") logger.info("Merging video and audio")
_, result = await execute( _, result = await execute(
f'{FFMPEG_PATH} -i "{video_temp_path}" -i "{audio_temp_path}" ' f'{FFMPEG_PATH} -i "{video_temp_path}" -i "{audio_temp_path}" '
f"-c:v copy -c:a copy -strict experimental " f"-c:v copy -c:a copy -movflags +faststart "
f'-y "{video_path}"' f'-y "{video_path}"'
) )
if result != 0: if result != 0:
@ -250,22 +286,34 @@ async def go_upload(v: Video, p_num: int, m: Message):
if not video_path.exists(): if not video_path.exists():
await fail_edit(m, "视频文件不存在") await fail_edit(m, "视频文件不存在")
return return
video_jpg_path = cache_dir / f"{v.get_aid()}_{p_num}.jpg"
try: try:
video_duration = await get_video_duration(video_path)
video_height, video_width = await get_video_height_width(video_path)
await take_screenshot(video_path, video_jpg_path, video_duration)
logger.info(f"Uploading {video_path}") logger.info(f"Uploading {video_path}")
await bot.send_video( await bot.send_video(
chat_id=m.chat.id, chat_id=m.chat.id,
video=str(video_path), video=str(video_path),
duration=video_duration,
width=video_width,
height=video_height,
thumb=str(video_jpg_path),
supports_streaming=True, supports_streaming=True,
progress=go_upload_progress, progress=go_upload_progress,
progress_args=(m,), progress_args=(m,),
) )
logger.info(f"Upload {video_path} success") logger.info(f"Upload {video_path} success")
except BilibiliDownloaderError as e:
await fail_edit(m, e.MSG)
return
except Exception as e: except Exception as e:
logger.exception("Uploading video failed") logger.exception("Uploading video failed")
await fail_edit(m, f"上传失败:{e}") await fail_edit(m, f"上传失败:{e}")
return return
finally: finally:
safe_remove(video_path) safe_remove(video_path)
safe_remove(video_jpg_path)
if m.id in MESSAGE_MAP: if m.id in MESSAGE_MAP:
del MESSAGE_MAP[m.id] del MESSAGE_MAP[m.id]
if m.id in UPLOAD_MESSAGE_MAP: if m.id in UPLOAD_MESSAGE_MAP: