• 我的首页
  • 星空画廊

My thought on web

Think what ? think

parallel

分布式x264编码的简易实现

2015年5月19日 by caoli5288 Leave a Comment

无论是x264工具本身,还是ffmpeg好像都没有分布式的实现。但是现实场景中,我们可能需要分布式的编码环境,因为现在高质量的视频需求,对比低下的编码速度,实在是令人发指。好在,伟大的GNU提供了一个通用的分布式实现工具”parallel”,借助这个简易的工具,配合另外一些工具,我们可以很轻易的实现分布式编码。

// 现在我把代码放在github上了,下面的演示代码是比较古老的版本

所有需要的工具:
– parallel
– rsync
– x264
– ffmpeg(optional)
– mkvtoolnix

其中rsync是被parallel所需要。我个人的需求场景是把视频编码任务分布到服务器上,本机(笔记本)并不承担视频编码任务。由于音频的编码速度较快(基本音速),而且nero的音频编码器没有64位元的二进制文件(然而服务器是64位的)所以由本机承担。然而实际部署到集群的话,肯定是需要任意节点同时承担视频音频编码任务,终端只做提交。下面的代码只作演示。

#!/bin/bash

function argnumb() {
    echo $#
}

function vencode() {(
    COPTS="-vcodec libx264 -tune psnr -preset placebo"
    if [ "$FOPTS" ]; then
        COPTS="$FOPTS $COPTS"
    fi
    ffmpeg -y -v quiet -i $1 $COPTS $2
)}

function encodec() {(
    # 在本地编码音频流
    if   [ ! $ANONE ] && [ $ACOPY ]; then
        ffmpeg -v quiet -i $1 -vn -codec copy .$1.tmp.m4a
    elif [ ! $ANONE ]; then
        ffmpeg -v quiet -i $1 -vn -f wav - |
            neroAacEnc -q 0.3 -ignorelength -if - -of .$1.tmp.m4a
    fi
    # 在本地分割视频流
    mkvmerge -q --no-audio -o .$1.tmp.mkv --split 2048k $1
    # 任务分布到服务器
    find . -name ".$1.tmp*mkv"  |
        parallel --env vencode  \
                 --env FOPTS    \
                 -S 1/root@one.mengcraft.com    \
                 -S 1/root@three.mengcraft.com  \
                 -S 1/root@four.mengcraft.com   \
                 -S 1/root@five.mengcraft.com   \
                 --trc {.}.target.mkv   \
                 vencode {} {.}.target.mkv
    # 计算合并视频参数
    R=`find . -name ".$1.tmp*target.mkv" | sort`
    T=`argnumb $R`
    J=0
    for I in $R; do
        S="$S -S -T --no-global-tags --no-chapters"
        if [[ $J > 0 ]]; then
            S="$S + "
        fi
        S="$S $I"
        J=$[J+1]
    done
    # 开始合并视频文件
    mkvmerge -q -o .$1.tmp.mkv $S
    # 备份原视音频文件
    if [ "$1" = "$2" ]; then
        mv $1 ${1}.bak
    fi
    # 混流视频音频轨道
    if [ $ANONE ]; then
        ffmpeg -y -v quiet -i .$1.tmp.mkv -codec copy $2
    else
        ffmpeg -y -v quiet -i .$1.tmp.mkv -i .$1.tmp.m4a -codec copy $2
    fi
    # 删除不用了的文件
    rm -rf .$1.tmp*
)}

if [[ $# < 1 ]]; then
    echo "No input file(s) define."
    exit 1
fi

export -f argnumb
export -f vencode
export -f encodec

parallel encodec {} {.}.mp4 ::: $@

在实践过程中,出现的几个坑提一下。
– 分割文件的事后容器选MKV,这个玩意通用程度比较高的。
– encodec函数前后用括号括起来,否则会被拆成行平行执行。
– 合并输出走sort再排序下,偶尔find出来的文件是乱序的。
– 在CentOS6用ffmpeg替代x264,因为libc版本太低了。
– mkvmerge的合并参数远没有那么简单,很多博客都说错了。

Posted in: 笔记 Tagged: linux, parallel, x264, 分布式

标签

c docker dynamic fedora ffmpeg hevc java libmfx linux mingw mount mp4 NAS parallel qsv rime x264 x265 ZFS 事件 互联网 交叉编译 优化 分布式 反射 性能 文件系统 杂谈 游戏 站点 网卡 网络 自由 调优 透明代理

近期文章

  • lxc安装openwrt
  • NAS 文件系统方案的选择
  • 透明代理踩坑指北
  • QSV编码HEVC视频参数测试
  • FFmpeg中的几个新视频降噪滤镜

友情链接

  • 梦之地
  • Vultr

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org

文章归档

Copyright © 2021 My thought on web.

Omega WordPress Theme by ThemeHall