You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cyndilib转发NDI流时视频正常但音频丢失的问题求助

使用cyndilib v0.0.6转发NDI流时无音频的问题排查

问题描述

在Windows系统上使用cyndilib(v0.0.6)接收NDI源并进行转发(含分辨率调整等场景),当前遇到的问题是:对传入的NDI流进行解码或重编码后重新转发为新NDI流时,无法听到音频。原始NDI源同时包含音频和视频,已通过NDI Studio Monitor验证正常。

当前测试情况

  • 原始NDI流 → cyndilib+NDI SDK自定义查看器:可看到视频,但无音频输出
  • 原始NDI流 → cyndilib解码+调整分辨率→重编码NDI流:NDI Studio Monitor中可看到视频,但无音频
  • 原始NDI流 → NDI Studio Monitor:音视频均正常

测试代码

with Finder() as finder:
    time.sleep(2)
    finder.wait_for_sources(1.0)
    source = next((s for s in finder if s.name == source_name or s.stream_name == source_name), None)
    if not source:
        raise Exception(f"Source '{source_name}' not found")

    recv = Receiver(color_format=RecvColorFormat.BGRX_BGRA.value, bandwidth=RecvBandwidth.highest.value)
    vf, af = VideoFrameSync(), AudioFrameSync()
    recv.frame_sync.set_video_frame(vf)
    recv.frame_sync.set_audio_frame(af)
    recv.set_source(source)

    for _ in range(30):
        if recv.is_connected():
            break
        time.sleep(0.5)
    else:
        raise TimeoutError("Connection timed out")

    while True:
        recv.frame_sync.capture_video()
        if vf.get_resolution() != (0, 0) and vf.get_data_size() > 0:
            break
        time.sleep(1 / 30)

    xres, yres = vf.get_resolution()
    fps = vf.get_frame_rate()
    sender = Sender(f"NDISDK_{source_name}")
    vsf = VideoSendFrame()
    vsf.set_fourcc(vf.get_fourcc())
    vsf.set_resolution(xres, yres)
    vsf.set_frame_rate(fps)
    sender.set_video_frame(vsf)
    sender.open()

    audio_configured = False
    interval = 1.0 / fps

    try:
        while recv.is_connected():
            recv.frame_sync.capture_video()
            arr = vf.get_array()
            if arr is not None and arr.size > 0:
                sender.write_video(arr)

            if recv.frame_sync.capture_available_audio() > 0:
                if not audio_configured and af.num_samples > 0:
                    asf = AudioSendFrame()
                    asf.set_max_num_samples(af.num_samples)
                    sender.set_audio_frame(asf)
                    audio_configured = True
                aud = af.get_array()
                if aud is not None and aud.size > 0:
                    sender.write_audio(aud)

            time.sleep(interval)
    except KeyboardInterrupt:
        pass
    finally:
        try: sender.close()
        except: pass
        try: recv.disconnect()
        except: pass

核心疑问

  • 使用cyndilib设置音频转发时是否遗漏关键步骤?
  • cyndilib v0.0.6或Windows上的NDI SDK 6在音频转发上有已知问题或特性吗?
  • 如何调试确认音频帧已被正确捕获和发送?

环境信息

  • NDI SDK版本:6
  • cyndilib版本:0.0.6
  • Windows版本:10 Pro
  • NDI流类型:NDI HB

排查与解决方案

1. 音频配置的遗漏点

你的代码仅设置了音频采样数,缺少NDI音频必需的完整参数配置,需补充以下内容:

if not audio_configured and af.num_samples > 0:
    asf = AudioSendFrame()
    asf.set_max_num_samples(af.num_samples)
    # 新增关键音频参数配置
    asf.set_sample_rate(af.get_sample_rate())
    asf.set_num_channels(af.get_num_channels())
    asf.set_fourcc(af.get_fourcc())  # 必须与接收帧的音频格式匹配
    sender.set_audio_frame(asf)
    audio_configured = True

另外,需循环处理所有可用音频帧,避免只处理一次导致帧丢失:

# 替换原音频捕获逻辑
while recv.frame_sync.capture_available_audio() > 0:
    if not audio_configured and af.num_samples > 0:
        asf = AudioSendFrame()
        asf.set_max_num_samples(af.num_samples)
        asf.set_sample_rate(af.get_sample_rate())
        asf.set_num_channels(af.get_num_channels())
        asf.set_fourcc(af.get_fourcc())
        sender.set_audio_frame(asf)
        audio_configured = True
    aud = af.get_array()
    if aud is not None and aud.size > 0:
        sender.write_audio(aud)

2. cyndilib v0.0.6的特性说明

  • 该版本音频同步依赖AudioFrameSync的实时捕获,需确保在视频循环中优先处理音频,避免帧堆积
  • 部分用户反馈处理高带宽NDI HB流时,af.get_array()可能返回空,需添加参数校验

3. 调试验证方法

  • 捕获阶段验证:添加日志打印关键参数,确认音频帧是否被正确捕获
    if recv.frame_sync.capture_available_audio() > 0:
        print(f"可用音频帧数: {recv.frame_sync.capture_available_audio()}")
        print(f"采样数: {af.num_samples}, 采样率: {af.get_sample_rate()}, 声道数: {af.get_num_channels()}")
        aud = af.get_array()
        print(f"音频数组大小: {aud.size if aud is not None else 0}")
    
  • 发送阶段验证:检查sender.write_audio()的返回值(若有),确认发送状态
  • 对比测试:用NDI SDK官方C++示例测试同流,验证是否为cyndilib绑定问题
  • 开启NDI日志:设置环境变量NDI_DEBUG_LEVEL=3,查看音频捕获和发送的详细日志

内容的提问来源于stack exchange,提问作者Yash mandlik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:34:59