linuxQQ发送视频报错:no such file or directory, stat ‘/root/.config/QQ/nt_qq_**/nt_data/Video/2025-03/Thumb

报错场景

nonebot+napcat在接入插件链接分享解析器重制版nonebot-plugin-resolver2(1.7.0版本)时,在解析b站视频链接时,经常会发送视频失败,并报下面这段错误

报错详细代码

03-01 02:02:43 [INFO] nonebot | Event will be handled by Matcher(type='message', module=nonebot_plugin_resolver2.matchers.bilibili, lineno=42)
[Request][2025-03-01 02:02:43,478] 激活 buvid3: [0816D84D-6AB8-8F64-5032-17A4A7083FF363384infoc] 成功
03-01 02:02:47 [INFO] nonebot | Matcher(type='message', module=nonebot_plugin_resolver2.matchers.bilibili, lineno=42) running complete
03-01 02:02:47 [ERROR] nonebot | Running Matcher(type='message', module=nonebot_plugin_resolver2.matchers.bilibili, lineno=42) failed.
Traceback (most recent call last):
  File "<string>", line 17, in <module>
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/__init__.py", line 337, in run
    get_driver().run(*args, **kwargs)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/drivers/fastapi.py", line 187, in run
    uvicorn.run(
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/uvicorn/main.py", line 579, in run
    server.run()
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/uvicorn/server.py", line 66, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
    return runner.run(main)
  File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/utils.py", line 254, in run_coro_with_shield
    return await coro
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/message.py", line 506, in check_and_run_matcher
    await _run_matcher(
> File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/message.py", line 458, in _run_matcher
    await matcher.run(bot, event, state, stack, dependency_cache)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/internal/matcher/matcher.py", line 926, in run
    await self.simple_run(bot, event, state, stack, dependency_cache)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/internal/matcher/matcher.py", line 863, in simple_run
    await handler(
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/dependencies/__init__.py", line 113, in __call__
    return await cast(Callable[..., Awaitable[R]], self.call)(**values)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot_plugin_resolver2/matchers/bilibili.py", line 312, in _
    await bilibili.send(await get_video_seg(video_path))
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/internal/matcher/matcher.py", line 570, in send
    return await bot.send(event=event, message=_message, **kwargs)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/adapters/onebot/v11/bot.py", line 237, in send
    return await self.__class__.send_handler(self, event, message, **kwargs)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/adapters/onebot/v11/bot.py", line 190, in send
    return await bot.send_msg(**params)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/internal/adapter/bot.py", line 176, in call_api
    raise exception
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/internal/adapter/bot.py", line 128, in call_api
    result = await self.adapter._call_api(self, api, **data)
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/adapters/onebot/v11/adapter.py", line 175, in _call_api
    return handle_api_result(await self._result_store.fetch(seq, timeout))
  File "/root/ali-tsugu-test01/.venv/lib/python3.12/site-packages/nonebot/adapters/onebot/v11/utils.py", line 58, in handle_api_result
    raise ActionFailed(**result)
nonebot.adapters.onebot.v11.exception.ActionFailed: ActionFailed(status='failed', retcode=1200, data=None, message="ENOENT: no such file or directory, stat '/root/.config/QQ/nt_qq_7****6135d56846/nt_data/Video/2025-03/Thumb/664a0871a3c5d76ed43ff4445a05fd0a_0.png'", wording="ENOENT: no such file or directory, stat '/root/.config/QQ/nt_qq_7****6135d56846/nt_data/Video/2025-03/Thumb/664a0871a3c5d76ed43ff4445a05fd0a_0.png'", echo='5')

报错分析

读代码可知,报错源于/root/.config/QQ/nt_qq_7****6135d56846/nt_data/Video/2025-03/Thumb/664a0871a3c5d76ed43ff4445a05fd0a_0.png该路径的图片缺少,而这个图片是QQ在用户发送视频时自动生成的预览缩略图。
而我们查看同目录上一级下的Ori文件夹,以及/root/.config/QQ/NapCat/temp、和/root/.cache/nonebot2/nonebot_plugin_resolver2这三处地方都可以看到,视频实际上正常下载成功了,具体代码是通过下载视频流和音频流,然后合并得到的。
合并代码位于/root/my-nonebot/.venv/lib/python3.12/site-packages/nonebot_plugin_resolver2/download/command.py150行附近:

async def merge_av(v_path: Path, a_path: Path, output_path: Path):
    """helper function to merge video and audio

    Args:
        v_path (Path): video path
        a_path (Path): audio path
        output_path (Path): ouput path

    Raises:
        RuntimeError: ffmpeg未安装或命令执行失败
    """
    logger.info(f"Merging {v_path.name} and {a_path.name} to {output_path.name}")
    # 构建 ffmpeg 命令, localstore already path.resolve()
    command = f'ffmpeg -y -i "{v_path}" -i "{a_path}" -c copy "{output_path}"'
    result = await asyncio.get_event_loop().run_in_executor(
        None,
        lambda: subprocess.call(
            command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
        ),
    )
    if result != 0:
        raise RuntimeError("ffmpeg未安装或命令执行失败")
    # 删除原始文件
    v_path.unlink()
    a_path.unlink()

然而这个合并的视频格式是 av1 编码,这是一种较新的视频编码格式,因此笔者推测QQ 可能对 av1 编码的支持不完善,导致无法正确处理或生成缩略图。

解决办法

为此,我们应该将视频格式修改为更常见的 h264 编码,修改上面的函数为:

import asyncio
import subprocess
from pathlib import Path
import logging

logger = logging.getLogger(__name__)

async def merge_av(v_path: Path, a_path: Path, output_path: Path):
    """合并视频和音频文件,并生成 QQ 兼容的 MP4 文件

    Args:
        v_path (Path): 视频文件路径
        a_path (Path): 音频文件路径
        output_path (Path): 输出文件路径

    Raises:
        RuntimeError: ffmpeg 未安装或命令执行失败
        FileNotFoundError: 视频或音频文件不存在
        PermissionError: 文件权限不足
    """
    logger.info(f"Merging {v_path.name} and {a_path.name} to {output_path.name}")

    # 确保输入文件存在
    if not v_path.exists() or not a_path.exists():
        raise FileNotFoundError("视频或音频文件不存在")

    # 构建 ffmpeg 命令
    # 使用 h264 视频编码和 aac 音频编码,确保 QQ 兼容
    command = [
        "ffmpeg",
        "-y",  # 覆盖输出文件
        "-i", str(v_path),  # 输入视频文件
        "-i", str(a_path),  # 输入音频文件
        "-c:v", "libx264",  # 使用 h264 视频编码
        "-c:a", "aac",  # 使用 aac 音频编码
        "-strict", "experimental",  # 允许使用实验性编码
        "-vf", "scale=1280:720",  # 限制分辨率为 1280x720(可选)
        "-b:v", "1000k",  # 限制视频码率为 1000k(可选)
        str(output_path),  # 输出文件
    ]

    try:
        # 使用 asyncio 创建子进程执行 ffmpeg 命令
        process = await asyncio.create_subprocess_exec(
            *command,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )

        # 等待命令执行完成
        stdout, stderr = await process.communicate()

        # 检查命令返回值
        if process.returncode != 0:
            logger.error(f"ffmpeg 命令执行失败: {stderr.decode()}")
            raise RuntimeError("ffmpeg 命令执行失败")

        logger.info(f"合并成功: {output_path.name}")

        # 合并成功后删除原始文件
        v_path.unlink()
        a_path.unlink()
        logger.info(f"已删除原始文件: {v_path.name}{a_path.name}")

    except FileNotFoundError:
        logger.error("ffmpeg 未安装")
        raise RuntimeError("ffmpeg 未安装")
    except PermissionError:
        logger.error("文件权限不足")
        raise PermissionError("文件权限不足")
    except Exception as e:
        logger.error(f"合并失败: {str(e)}")
        raise RuntimeError(f"合并失败: {str(e)}")

然后视频便发送成功了,问题解决。

特别感谢:deepseek

<think>好的,我现在需要解决用户在运行Ruby上传命令时遇到的“No such file or directory”错误。用户提到引用了Docker相关的路径问题,可能和Docker的卷配置有关。首先,我应该从常见原因入手,逐步排查问题。 首先,用户可能输入了错误的文件路径。需要检查命令中的路径是否正确,尤其是绝对路径和相对路径的问题。比如,用户可能在Docker容器中使用相对路径,而容器的工作目录与实际文件位置不符。建议用户使用绝对路径,或者在运行命令前确认当前目录。 其次,Docker的卷挂载问题。根据引用内容,Docker在非C盘路径下可能有支持问题。如果用户将项目放在其他驱动器(比如D盘),而Docker Desktop默认只挂载C盘,这会导致容器内无法访问其他盘的文件。需要用户到Docker设置中启用文件共享,添加对应的驱动器。 然后,文件权限问题也可能导致错误。检查宿主机的文件权限,确保Docker有权限读取该文件。可能需要使用`chmod`调整权限,或者在Docker命令中加入`--user`参数指定用户。 还有,用户可能在Ruby代码中硬编码了路径,导致容器内路径与实际挂载路径不一致。需要确认代码中的路径是否与挂载点匹配,比如宿主机的`/host/path`对应容器的`/container/path`。 另外,检查Dockerfile中的路径是否正确,比如`COPY`或`ADD`指令是否引用了存在的文件。构建上下文是否正确,避免遗漏必要文件。 最后,考虑容器内的环境变量是否影响路径解析。比如`RAILS_ROOT`等变量是否指向正确的位置,或者是否在容器启动时正确设置。 总结下来,应该分步骤引导用户检查路径、Docker配置、权限、代码中的路径处理等方面,确保每个环节都正确。同时结合用户的具体错误信息,比如具体的文件路径,可以更精准地定位问题。如果用户提供更多细节,比如完整的命令和错误日志,可以进一步缩小排查范围。</think>### 解决Ruby上传命令报错"No such file or directory"的步骤 #### 1. 检查文件路径格式(Docker特有) - **Windows系统**:若使用Docker且文件路径在非C盘,需先在Docker Desktop的`Settings > Resources > File Sharing`中添加对应驱动器[^1] - **路径转换示例**: ```bash # 错误写法(D盘直接映射) docker run -v d:/project:/app my_image # 正确写法(需通过Docker配置共享D盘后使用) docker run -v /d/project:/app my_image ``` #### 2. 验证文件路径存在性 ```ruby # 在Ruby代码中添加预检查 file_path = 'uploads/test.txt' raise "文件不存在:#{File.expand_path(file_path)}" unless File.exist?(file_path) ``` #### 3. 检查目录权限 ```bash # 查看目录权限 ls -ld /path/to/directory # 设置写权限(示例) chmod -R a+w /host/upload_dir ``` #### 4. Docker卷挂载验证 ```dockerfile # Dockerfile示例(确保上下文包含目标文件) COPY . /app WORKDIR /app ``` #### 5. 环境变量配置检查 ```ruby # 在Ruby中输出调试信息 puts "当前工作目录:#{Dir.pwd}" puts "环境变量PATH:#{ENV['PATH']}" ``` ### 典型解决方案流程 ```mermaid graph TD A[报错信息] --> B{路径是否存在?} B -->|是| C{Docker卷映射正确?} B -->|否| D[修正文件路径] C -->|是| E{文件权限正确?} C -->|否| F[调整Docker设置] E -->|是| G[检查Ruby代码逻辑] E -->|否| H[修改权限或用户] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值