调教 GPT 实现多流合一定时轮播

昨天接到一个需求,要实现4-6路流合一,做定时切换的需求,由于没有现成的云导播台,于是首先想到使用 FFMPEG 命令实现。

由于需要添加台标、背景音乐之的类,各种 Filter 写到手软,第一时间想偷懒,就想用GPT 协助实现。

我用的是白嫖 GPT 3.5,Prompt 是 `我有3路直播流,分别是rtmp://x/sz-live/20230615-s01, rtmp://x/sz-live/20230615-s02, rtmp://x/sz-live/20230615-s03
我想将这3路流合并成一路流,按30秒的时间进行切换输出,请给我一个命令

GPT 飞快的给出了一系列命令,经过几个回合的调教,最终 GPT 认输了。
期间经历了 FFMPEG 版本的问题,GPU 版本的问题,以及 Docker 中运行FFMPEG 的问题。

总的来说,按 GPT 生成的命令执行以后,遇到报错,发给 GPT 以后可以正确识别到报错的原因,并能给出相应的解决办法。

最后遇到了 FFMPEG 多路信号平滑切换的问题,GPT 给出的命令如下:

要实现流切换过程中的平滑过渡,避免出现断流情况,你可以考虑使用FFmpeg的动态画面转换(Dynamic Picture Resizing)功能。该功能允许在切换流时动态调整输出流的分辨率和比特率,以实现平滑过渡。

以下是一个示例命令,结合了动态画面转换和流切换的功能:

ffmpeg -i rtmp://play.baidu.com/sz-live/20230615-s01 -i rtmp://play.baidu.com/sz-live/20230615-s02 -i rtmp://play.baidu.com/sz-live/20230615-s03 -filter_complex "[0:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1[v0]; [1:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1[v1]; [2:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1[v2]; [v0][v1][v2]concat=n=3:v=1:a=0[outv]" -map "[outv]" -c:v libx264 -preset veryfast -crf 18 -f flv rtmp://output-url

在上述命令中,我们在每个输入流的处理链中添加了setsar=1过滤器,用于设置输出流的样纵横比(Sample Aspect Ratio)为1:1,以避免在切换流时出现变形。

此外,我们还指定了-c:v libx264 -preset veryfast -crf 18等参数,用于指定输出流的视频编码器和相关设置。你可以根据需要调整这些参数。

请确保替换示例命令中的输入和输出URL,并运行命令。这样修改后的命令应该能够实现流切换过程中的平滑过渡,避免出现断流情况,并且输出流的分辨率为1920×1080。

后来我又想到,如果使用 OBS 实现的话,如何实现,GPT 根据指引,一步步生成了 Python 版本的Script

import obspython as obs

timer_interval = 10  # 切换场景的时间间隔(秒)
scenes = []  # 场景列表
current_scene_index = 0  # 当前场景索引
timer_id = None  # 定时器ID

def switch_scene():
    global current_scene_index

    scene_count = len(scenes)
    if scene_count == 0:
        return

    scene_name = scenes[current_scene_index]
    obs.script_log(obs.LOG_INFO, "切换场景:" + scene_name)

    if obs.obs_frontend_streaming_active():
        obs_frontend_set_current_scene(scene_name)
    else:
        obs_frontend_set_current_preview_scene(scene_name)

    current_scene_index = (current_scene_index + 1) % scene_count

def timer_callback():
    switch_scene()

def obs_frontend_set_current_scene(scene_name):
    scene = obs.obs_get_source_by_name(scene_name)
    obs.obs_frontend_set_current_scene(scene)
    obs.obs_source_release(scene)

def obs_frontend_set_current_preview_scene(scene_name):
    scene = obs.obs_get_source_by_name(scene_name)
    obs.obs_frontend_set_current_preview_scene(scene)
    obs.obs_source_release(scene)

def script_description():
    return "定时切换场景脚本"

def script_update(settings):
    global timer_interval

    timer_interval = obs.obs_data_get_int(settings, "timer_interval")

    # 停止旧定时器
    if timer_id is not None:
        obs.timer_remove(timer_id)
        timer_id = None

    if timer_interval > 0:
        # 启动新定时器
        timer_id = obs.timer_add(timer_callback, timer_interval * 1000)

def script_load(settings):
    global scenes

    scene_list = obs.obs_frontend_get_scene_names()
    scenes = [scene for scene in scene_list]
    obs.source_list_release(scene_list)

def script_properties():
    props = obs.obs_properties_create()

    # 添加定时参数
    obs.obs_properties_add_int(props, "timer_interval", "切换间隔(秒)", 1, 3600, 1)

    return props

调教过程中的几个体验

  1. GPT 对各种最新的文档,索引速度是非常快的,我用的 OBS 29.1版本,GPT可以准确提示哪些 API 是过期的
  2. GPT的代码还是无法完整运行,需要经过指引,进行针对性的优化
  3. 有几个地方有问题,我按 GPT 生成的代码中的关键接口,google 到原始出处以后,告诉 GPT 有问题,进行多次修改
  4. 基本代码有了以后,最终还是在自己的修改和调试下验证通过
  5. 遇到了两次睁眼说瞎话和上下文混乱
  6. 整体上没有任何 OBS 的开发经验,可以在 GPT 的引导下找到思路,减少了很多不必要的学习时间。

最后的成果

发表评论