Skip to content

WARNING

弹幕压制对硬件要求较高,就是说硬件性能越高弹幕压制就快,硬件性能过低就别试了。

分段后处理中的弹幕压制

下面是一个简单的分段后处理中压制弹幕的 python 脚本示例,保存到 Termux 的 ~ 目录(biliup运行目录),赋予可执行权限。

  • 使用到 DanmakuFactory,自行下载或编译,复制到脚本同目录,并赋予可执行权限。
  • 弹幕样式设置,请查看 DanmakuFactory 官方文档。
  • 非 Termux 使用,请自行设置合适的 -hwaccel 参数(或者直接使用 auto )和 h264 编码器。
ffmpeg -hwaccels                   # 查看硬件加速器
ffmpeg -codecs | grep h264         # 查看 h264 编解码器(linux)
ffmpeg -codecs | findstr h264      # 查看 h264 编解码器(windows)
  • Windows 中建议使用 d3d11va,如果不在乎 cpu 使用率,可以使用 opencl 或 vulkan 硬件加速,速度会更快一些。
  • 测试骁龙 865 使用脚本中的参数压制 1080p 视频的速度可达 2x。
  • 注意源视频文件的扩展名以防止文件覆盖。
  • 编码参数 -profile 和 -level 最好同时指定,仅指定 -profile 在部分设备上会出现编码失败
import os
import sys
import glob
import subprocess
import datetime

def is_termux():
    return 'com.termux' in os.getenv('PREFIX', '')

def encode():
    # 读取标准输入的内容
    video = sys.stdin.readline().strip()
    xml = sys.stdin.readline().strip()

    mp4 = os.path.splitext(video)[0] + '.mp4'
    # 避免 Windows 中绝对路径的转义问题
    ass = os.path.splitext(os.path.basename(xml))[0] + '.ass'

    # 查找当前文件夹 DanmakuFactory 可执行文件
    danmaku_file = None
    for file in glob.glob(os.path.join(os.getcwd(), 'DanmakuFactory*')):
        if os.path.isfile(file):
            danmaku_file = file
            break

    subprocess.run(f'{danmaku_file} -i {xml} -o {ass} -S 50 -O 230 --ignore-warnings', shell=True, check=True, stdout=subprocess.DEVNULL)
    print("开始压制时间:", datetime.datetime.now())
    subprocess.run(f'ffmpeg -hwaccel mediacodec -i {video} -vf ass={ass} -c:v h264_mediacodec -c:a copy -crf 18 -b:v 12M -profile:v high -level 4.2 -v quiet -y {mp4}', shell=True, check=True, stdout=subprocess.DEVNULL)
    print("结束压制时间:", datetime.datetime.now())
    os.remove(ass)
    os.remove(video)
    os.remove(xml)

if __name__ == "__main__":
    if is_termux():
        try:
            subprocess.run('termux-wake-lock', shell=True, check=True)
            encode()
        except Exception as e:
            print(f"error: {e}")
            sys.exit(1)
        finally:
            subprocess.run('termux-wake-unlock', shell=True, check=True)
    else:
        try:
            encode()
        except Exception as e:
            print(f"error: {e}")
            sys.exit(1)

MIT License.