f2 icon indicating copy to clipboard operation
f2 copied to clipboard

[QUESTION] fetch_user_live_videos和fetch_user_live_videos_by_room_id 下载直播流

Open CCMonkeyss opened this issue 8 months ago • 2 comments

  • [ ] ~~在提问时请注意不要包含个人敏感信息~~
  • [ ] 我明白我的提问可能不会得到明确回复或解决。

问题描述

使用示范代码配合webcast_id下载直播流是正常的,改成room_id就失败,传回的值都为空,不知道哪里没改好。 room_id是有效的,可以拿来下载wss弹幕。 因为webcast_id没办法抓到单人语音直播间,所以只能选择用room_id。

= RESTART: C:\Users\CC\Downloads\f2弹幕下载\douyin_downloader.py INFO 处理房间号: 7538611852025023284 的直播数据
INFO 直播ID:未知,用户:未知,直播间:无标题,状态:未知状态,观看人数:0 ERROR 直播间ID:7538611852025023284 下载失败:'NoneType' object has no
attribute 'items'

其他细节

使用的代码如下:

import asyncio
import traceback
from f2.apps.douyin.handler import DouyinHandler from f2.apps.douyin.db import AsyncUserDB from f2.apps.douyin.dl import DouyinDownloader from f2.utils.conf_manager import ConfigManager from f2.log.logger import logger # 确保导入logger from f2.apps.douyin.utils import TokenManager from f2.cli.cli_console import RichConsoleManager

全局配置参数,保护敏感信息

kwargs = { "headers": { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0", "Referer": "https://www.douyin.com/", }, "proxies": {"http://": None, "https://": None}, # 指定模式 "mode": "live", } | ConfigManager("conf/app.yaml").get_config("douyin")

实例化下载器和处理器

dydownloader = DouyinDownloader(kwargs) dyhandler = DouyinHandler(kwargs)

async def download_live_stream( room_id: str, # 接收的是字符串类型的 room_id ): """ 下载单个直播间的直播流,直到流断开

Args:
    room_id (str): 直播间ID (Room ID)
"""
try:
    room_id_str = str(room_id)
    logger.debug(f"尝试获取直播间 {room_id_str} 信息...")

    # 获取直播间信息
    live = await dyhandler.fetch_user_live_videos_by_room_id(room_id=room_id_str)
    
    if live is None:
        logger.error(f"无法获取直播间 {room_id_str} 信息,API 返回 None")
        return

    logger.debug(f"直播间信息: {live._to_dict()}")  # 查看返回的数据结构

    if live.live_status != 2:
        logger.info(f"直播间 {room_id_str} 当前未开播 (状态: {live.live_status})")
        return

    async with AsyncUserDB("douyin_users.db") as audb:
        user_path = await dyhandler.get_or_add_user_data(
            kwargs, live.sec_user_id, audb
        )

    logger.debug(
        f"[bold green]开始下载直播间ID:{room_id_str} 的直播流...[/bold green]"
    )
    await dydownloader.create_stream_tasks(kwargs, live._to_dict(), user_path)
    logger.info(
        f"[bold green]直播间ID:{room_id_str} 直播流已结束,下载完成。[/bold green]"
    )

except Exception as e:
    logger.error(f"[bold red]直播间ID:{room_id_str} 下载失败:{e}[/bold red]")

主函数,用于下载单个直播间的直播流

async def main(room_id: str): await download_live_stream(room_id)

if name == "main": try: room_id = "7538611852025023284" # 你可以在这里传入任何需要下载的房间ID asyncio.run(main(room_id)) except KeyboardInterrupt: logger.info("[bold yellow]程序已手动停止[/bold yellow]") except Exception as e: logger.error(f"[bold red]程序运行时出现异常: {e}[/bold red]") logger.error(traceback.format_exc())

CCMonkeyss avatar Aug 15 '25 02:08 CCMonkeyss

Similarity Issues

  1. 70% #357
  2. 70% #356
  3. 70% #355
  4. 70% #348
  5. 70% #347
  6. 70% #305

github-actions[bot] avatar Aug 15 '25 02:08 github-actions[bot]

Hi @CCMonkeyss! I'm Dosu and I’m helping the f2 team.

webcast_id 和 room_id 是抖音直播的两个不同标识符,分别对应不同的 API 接口,不能混用。用 room_id 下载直播流时,fetch_user_live_videos_by_room_id 方法会调用专门的接口获取直播数据,但如果 API 返回的数据结构不完整(比如缺少 sec_user_id、live_status 等关键字段),或者 room_id 对应的直播间不是“正在直播”状态,就会返回 None,导致你看到的 'NoneType' object has no attribute 'items' 错误。即使 room_id 能用于弹幕(wss),也不一定能用于下载直播流,因为弹幕和视频流的接口不同,返回的数据结构也不同。

建议排查:1)room_id 是否对应正在直播的房间(live_status 必须为 2);2)API 请求是否带上了完整的 cookie(部分直播间需要登录态);3)检查 API 返回的数据结构是否完整,可以在 debug 日志里打印 live._to_raw() 或 live._to_dict() 看实际内容;4)确认 room_id 来源是否为 APP 分享的直播链接(不是短链 r_id)参考

详细接口和参数说明见 官方文档

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

dosubot[bot] avatar Aug 15 '25 03:08 dosubot[bot]