Cell/B.E. & SpursEngine プログラミング
Home記事一覧BBS

Linux上でSpursEngineを使用して動画のトランスコードをする

PCのLinux上でSpursEngineを使用して動画のトランスコードを行えるようにします。

環境はUbuntu 10.04 Lucid Lynxを想定しています。
PCにUbuntu 10.04 Lucid Lynxを「軽量」インストールするも合わせてご覧ください。

SpursEngine Linux SDK、clubミドルウェア・サンプルのインストール

SpursEngine Linux SDKに付属しているclubミドルウェア・サンプル・プログラムを利用してエンコードするので、あらかじめインストールしておきます。インストール方法は「PCにSpursEngine Linux SDKをインストールする」を参照してください。

ffmpeg、faacのインストール

端末(ROXTerm等)で以下のコマンドを入力してインストールします。

sudo apt-get --no-install-recommends install ffmpeg faac

SpursEngineトランスコードスクリプトのダウンロード、解凍、実行

以下のファイルをダウンロードしてホームディレクトリに置きます。

ダウンロード:spurs_enc_script.tar.gz

端末で、

tar xzf spurs_enc_script.tar.gz

cd spurs_enc_script

このディレクトリで以下のようにコマンドを入力してトランスコードします。

./ench264.py プロファイル名 入力ファイル名 出力ファイル名

(例)mpgファイルを1920x1080ドット、プログレッシブのMP4ファイルにトランスコードする場合
./ench264.py p1920 /media/disk/douga.mpg /media/disk/douga.mp4

現在選択可能なプロファイルは以下の通りです。
p1920 : 1920x1080 プログレッシブ 16:9 固定量子化
p1440 : 1440x1080 プログレッシブ 16:9 固定量子化
i1440 : 1440x1080 インターレース 16:9 固定量子化
p1280 : 1280x720 プログレッシブ 16:9 固定量子化
i720 : 720x480 インターレース 4:3 固定量子化
p640 : 640x480 プログレッシブ 4:3 固定量子化
iphone : 480x272 プログレッシブ 16:9 CBR1.5Mbps iPhone向け
psp : 480x272 プログレッシブ 16:9 VBR平均1.5Mbps最大2.25Mbps PSP向け

トランスコード用スクリプト解説

現時点での仕様

トランスコード用スクリプト・ソースコード(参考)

ench264.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, struct, re, codecs, commands, time, subprocess, md5

def do_enc():
  # 一時ファイルを保存するディレクトリ
  tmp_dir = '/tmp/'
  # コマンドライン引数を取得
  if len(sys.argv) < 4:
    print 'usage: ' + sys.argv[0] + ' encode_setting_name input_filename output_filename'
    print '  encode_setting_name: p1920, p1440, i1440, p1280, i720, p640, iphone, psp'
    sys.exit()
  my_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
  enc_profile = sys.argv[1]
  full_path_r = os.path.abspath(sys.argv[2])
  full_path_w = os.path.abspath(sys.argv[3])

  # プロファイル別パラメーター
  # 書式: 'プロファイル名': ['エンコードパラメーターファイル名', 'デインターレースとスケーリングの設定', 'オーディオビットレート', 'オーディオサンプリング周波数'],
  params = {
    'p1920': ['param_h264_1920_p.txt', '-deinterlace -s 1920x1080', '160', '48000'],
    'p1440': ['param_h264_1440_p.txt', '-deinterlace -s 1440x1080', '160', '48000'],
    'i1440': ['param_h264_1440_i.txt', '-s 1440x1080', '160', '48000'],
    'p1280': ['param_h264_1280_p.txt', '-deinterlace -s 1280x720', '160', '48000'],
    'i720': ['param_h264_720_i.txt', '-s 720x480', '160', '48000'],
    'p640': ['param_h264_640_p.txt', '-deinterlace -s 640x480', '160', '48000'],
    'iphone': ['param_h264_iphone.txt', '-deinterlace -s 480x272', '160', '48000'],
    'psp': ['param_h264_psp.txt', '-deinterlace -s 480x272', '128', '44100'],
    }

  if params.has_key(enc_profile):
    option_param_file = my_dir + '/' + params[enc_profile][0]
    option_size = params[enc_profile][1]
    option_aac = '-b ' + params[enc_profile][2] + ' --no-tns --no-midside'
    option_decode_out = '-sws_flags bicubic -ar ' + params[enc_profile][3] + ' -ac 2 -pix_fmt yuv420p'
  else:
    print 'error:format'
    sys.exit()

  option_decode_in = ''
  option_mux_in = ''
  option_mux_out = ''

  # SpursEngine SDKのインストールパス
  spurs_top = os.environ['HOME'] + '/SpursEngine_Linux_SDK_v1_5_3_2/release'
  spurs_encoder = spurs_top + '/sample/release/encoder'
  dir_w = os.path.dirname(full_path_w)
  name_wt = os.path.splitext(os.path.basename(full_path_w))[0]
  name_w = 'tmp_' + hex(hash(name_wt) + 0x80000000L)
  tmp_video = tmp_dir + name_w + '_tmp.h264'
  tmp_audio = tmp_dir + name_w + '_tmp.m4a'

  # 入力ファイルにアクセス可能か
  if not os.access(full_path_r, os.R_OK):
    print 'error:read file'
    sys.exit()

  # ライブラリのパスをセット
  os.environ['LD_LIBRARY_PATH'] = spurs_top + '/linux/lib'

  # 名前付きパイプを作成
  pipe_v1 = tmp_dir + name_w + '_v1.pipe'
  pipe_a1 = tmp_dir + name_w + '_a1.pipe'
  try:
    os.mkfifo(pipe_v1)
    os.mkfifo(pipe_a1)
  except:
    print 'error:mkfifo'

  # コマンド実行
  # デコード
  process1 = subprocess.Popen(['ffmpeg -y ' + option_decode_in + ' -i "' + full_path_r + '" ' + option_size + ' ' + option_decode_out + ' -f rawvideo ' + pipe_v1 + ' -acodec pcm_s16le -f wav ' + pipe_a1], shell=True)
  # 音声エンコード
  process2 = subprocess.Popen(['faac ' + option_aac + ' -o ' + tmp_audio + ' ' + pipe_a1 + ' >/dev/null 2>&1'], shell=True)
  # 映像エンコード
  process3 = subprocess.Popen([spurs_encoder + ' ' + pipe_v1 + ' ' + tmp_video + ' 1 ' + option_param_file + ' >/dev/null 2>&1'], shell=True)
  process3.wait()
  process2.wait()
  process1.wait()
  # Mux
  process4 = subprocess.Popen(['ffmpeg -y ' + option_mux_in + ' -i ' + tmp_video + ' -i ' + tmp_audio + ' -vcodec copy -acodec copy -f mp4 ' + option_mux_out + ' "' + full_path_w + '"'], shell=True)
  process4.wait()

  # 一時ファイルを削除
  os.unlink(pipe_v1)
  os.unlink(pipe_a1)
  os.unlink(tmp_video)
  os.unlink(tmp_audio)


do_enc()
sys.exit()

sample_batch.sh
#!/bin/sh

# バッチトランスコードの例
# 様々な形式で複数のファイルを自動でトランスコードできます。
# ファイルのパスやファイル名、プロファイル名を編集して実行して下さい。
# 実行方法: ./sample_batch.sh

./ench264.py p1280 /media/disk/file01.mpg /media/disk/file01.mp4
./ench264.py p640 /media/disk/file02.avi /media/disk/file02.mp4
./ench264.py iphone /media/disk/file03.wmv /media/disk/file03.mp4

sample_batch2.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, struct, re, codecs, commands, time, subprocess

def transcode(enc_profile, file_path_r, file_path_w):
  my_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
  process1 = subprocess.Popen([my_dir + '/ench264.py ' + enc_profile + ' "' + file_path_r + '" "' + file_path_w + '"'], shell=True)
  process1.wait()
  return


def do_job(directory, directory_w, extension, enc_profile):
  # 指定ディレクトリ直下の指定拡張子のファイルに対して、同名の拡張子.mp4のファイルが存在しなければトランスコードして.mp4ファイルを作成。(つまり、まだトランスコードされていないファイルを全てトランスコードする。)
  full_directory = os.path.abspath(directory)
  full_directory_w = os.path.abspath(directory_w)

  # 指定ディレクトリが存在するか
  if not (os.path.isdir(full_directory) or os.path.isdir(full_directory_w)):
    print 'error:bad directory'
    sys.exit()

  files = os.listdir(full_directory)

  for filename in files:
    root, ext = os.path.splitext(filename)
    if (ext == extension):
      file_path_r = full_directory + '/' + filename
      file_path_w = full_directory_w + '/' + root + '.mp4'
      if os.path.isfile(file_path_r):
        if not os.path.exists(file_path_w):
          transcode(enc_profile, file_path_r, file_path_w)

  sys.exit()


# 指定ディレクトリの下位ディレクトリにあるファイルは処理しません。
# ディレクトリ階層を処理する場合はディレクトリごとにdo_job()を記述してください。
# do_job('動画のあるディレクトリ', '保存先ディレクトリ', '入力ファイルの拡張子', 'エンコードプロファイル名')
do_job('/media/disk/video', '/media/disk/mp4video', '.avi', 'p1280')

sys.exit()

H.264 Encoderのパラメータ一覧

「param_h264_〜.txt」には、以下のパラメーターを設定できます。

設定の詳細は、Windows版SpursEngine SDK(SDK1_5.rar)を解凍したディレクトリのSpursEngineSDK1_5_1026_2009/Document_Japanese/Manual/SRKj_APLSW10_VEncodeLib_Users_Guide_Rev1-2.pdfを参照して下さい。

パラメータ名デフォルト値説明
“Horizontal Size”1920ビデオの水平方向のピクセル数を指定します。
“Vertical Size”1080ビデオの垂直方向のピクセル数を指定します。
“Aspect Ratio Information Present Flag”true ※1アスペクト比情報の挿入・非挿入を選択します。
“Aspect Ratio Identification”“SAR 1:1”出力ストリームのアスペクト比をサンプルアスペクト比で指定します。
“SAR Width”1サンプルアスペクト比の水平方向のサイズを指定します。
“SAR Height”1サンプルアスペクト比の垂直方向のサイズを指定します。
“Frame Rate Code”“29.97fps”フレームレートを指定します。
“Data Rate Control”“VBR”出力ビットレートの制御方法を指定します。
“Bit Rate”10000出力ストリームのビットレートを kbps単位で指定します。
“Max Bit Rate”15000VBR 時のストリームの最大ビットレートを kbps 単位で指定します。
“Profile Identification”“High Profile”プロファイルを指定します。
“Level Identification”“level 4”レベルを指定します。
“Constraint Set 0 Flag”false ※2constraint_set0_flag のオン・オフを選択します。
“Constraint Set 1 Flag”false ※2constraint_set1_flag のオン・オフを選択します。
“Constraint Set 2 Flag”false ※2constraint_set2_flag のオン・オフを選択します。
“Constraint Set 3 Flag”false ※2constraint_set3_flag のオン・オフを選択します。
“Sequence Scaling List Mode”“Flat Scaling List”使用するスケーリングリストを指定します。
“Scaling List 4x4 Intra Y”Default_4x4_Intra
※3
イントラブロックの Y 成分用 4x4 スケーリングリストを指定します。
“Scaling List 4x4 Intra Cb”Default_4x4_Intra
※3
イントラブロックの Cb 成分用 4x4 スケーリングリストを指定します。
“Scaling List 4x4 Intra Cr”Default_4x4_Intra
※3
イントラブロックの Cr 成分用 4x4 スケーリングリストを指定します。
“Scaling List 4x4 Inter Y”Default_4x4_Inter
※3
インターブロックの Y 成分用 4x4 スケーリングリストを指定します。
“Scaling List 4x4 Inter Cb”Default_4x4_Inter
※3
インターブロックの Cb 成分用 4x4 スケーリングリストを指定します。
“Scaling List 4x4 Inter Cr”Default_4x4_Inter
※3
インターブロックの Cr 成分用 4x4 スケーリングリストを指定します。
“Scaling List 8x8 Intra Y”Default_8x8_Intra
※3
イントラブロックの Y 成分用 8x8 スケーリングリストを指定します。
“Scaling List 8x8 Inter Y”Default_8x8_Inter
※3
インターブロックの Y 成分用 8x8 スケーリングリストを指定します。
“Gaps in Frame Number Value Allowed Flag”false ※2不連続なフレーム番号を許可するか否かを選択します。
“Entropy Coding Mode”“CAVLC”使用する可変長符号方式を指定します。
“Picture Structure”“Top Field First, Field Coding”ストリームを構成するピクチャの構造を指定します。
“I-Frame Interval”15I フレームの間隔をフレーム数で指定します。
“Number of Consecutive B-Frames”2連続する B フレーム数を指定します。
“IDR-Frame Interval Factor”20IDR フレームが I フレーム何枚おきに挿入されるかを指定します。
“Stream Structure”“Pattern 0”選択したパターンによって、挿入する NALユニットの種類、および挿入位置が決まります。
“Overscan Information Present Flag”false ※2適切な表示方式を示すフラグ情報の挿入・非挿入を選択する。
“Overscan Appropriate Flag”false ※2オーバースキャンによる表示が適切か不適切かを選択する。
“Video Signal Type Present Flag”false ※2Video signal type 情報の挿入・非挿入を選択します。
“Video Format”“Component”ビデオフォーマットを指定します。
“Video Full Range Flag”false ※2信号値の表現にアナログコンポーネント信号のレンジを用いるか否かを選択します。
“Colour Description Present Flag”false ※2Colour description 情報の挿入・非挿入を選択します。
“Colour Primaries”“ITU-R Rec. BT.709-5”画像の Colour primaries を指定します。
“Transfer Characteristics”“ITU-R Rec. BT.709-5”画像の Transfer characteristics を指定します。
“Matrix Coefficients”“ITU-R Rec. BT.709-5”画像の Matrix coefficients を指定します。
“Chroma Location Information Present Flag”false ※2色差成分のサンプル位置を示す情報を挿入するか否かを選択します。
“Chroma Sample Location Type Top Field”“type 0”トップフィールドの色差成分のサンプル位置を指定します。
“Chroma Sample Location Type Bottom Field”“type 0”ボトムフィールドの色差成分のサンプル位置の値を指定します
“Timing Information Present Flagtrue ※1Timing information の挿入・非挿入を選択します。
“Timing Information Automatic Assignment Flag”true ※1Timing information がフレームレートに基づいて自動計算するか否かを選択します。
“Number of Units in Tick”1001num_units_in_tick の値を指定します。
“Time Scale”60000time_scale の値を指定します。
“SPS Interval Factor”1Sequence Parameter Set(SPS)が I フレーム何枚おきに挿入されるかを指定します。
“PPS Interval”1Picture Parameter Set(PPS)が何フレームおきに挿入されるかを指定します。
“CPB Size Automatic Assignment Flag”true ※1CPB サイズの自動計算の有効・無効を選択します。
“CPB Size”1525CPB サイズを 16,384bits 単位で指定します。
“Pan Scan Rectangle ID”0パンスキャン情報の ID を指定する。
“Pan Scan Rectangle Cancel Flag”false ※2パンスキャン情報を無視するか否か選択します。
“Pan Scan Count Minus 1”0パンスキャン情報が保持する表示領域の個数から 1 を引いた数を指定します。
“Pan Scan Rectangle Left Offset”{0, 0, 0} ※3パンスキャンの表示領域情報の左端位置を指定します。
“Pan Scan Rectangle Right Offset”{0, 0, 0} ※3パンスキャンの表示領域情報の右端位置を指定します。
“Pan Scan Rectangle Top Offset”{0, 0, 0} ※3パンスキャンの表示領域情報の上端位置を指定します。
“Pan Scan Rectangle Bottom Offset”{0, 0, 0} ※3パンスキャンの表示領域情報の下端位置を指定します。
“Pan Scan Rectangle Repetition Period”0Pan Scan Rectangle SEI の効果が持続するピクチャ数を指定します。
“Slice Split Mode”"Single Slice"スライスの分割モードを選択します。
"Number of Slices in I-Picture"1I ピクチャのスライス分割数を指定します。
"Number of Slices in B-Picture"1P ピクチャのスライス分割数を指定します。
"Number of Slices in P-Picture"1B ピクチャのスライス分割数を指定します。
"Bitstream Restriction Flag"false ※2bitstream_restriction_flag のオン・オフを選択します。
"Clock Timestamp Flag"false ※2Picture Timing SEI にタイムスタンプを挿入するか否かを選択します。
"Full Timestamp Flag"false ※2タイムスタンプをすべての Picture Timing SEI に挿入するか、時刻が変化した場合にのみ挿入するかを選択します。
"Timestamp Counting Type""Dropping of Zero Values"Picture Timing SEI 内にあるタイムスタンプのカウント方法を指定します。
"Start Timestamp Hours"0先頭 Picture Timing SEI のタイムスタンプの時数を指定します。
"Start Timestamp Minutes"0先頭 Picture Timing SEI のタイムスタンプの分数を指定します。
"Start Timestamp Seconds"0先頭 Picture Timing SEI のタイムスタンプの秒数を指定します。

※「param_h264_〜.txt」での設定は以下のようになります。
※1 trueは1と設定。
※2 falseは0と設定。
※3 数値リスト・行列は、「パラメーター名,リスト・行列のインデックス,数値」と設定します。
(例)
Scaling List 4x4 Intra Y,0,26
Scaling List 4x4 Intra Y,1,33
Scaling List 4x4 Intra Y,2,40
・・・

Special Thanks

録画人間の末路のkrmmk3さんのSpursEngine H.264エンコーダ 実験プログラムサポート&他ソフト紹介ページではSpursEngineのエンコードに関する情報や、Lalfさんの作成されたSpursEngine用ソフトの情報が公開されています。このページもご紹介いただきました。

GroupTRONのLalfさんのサイトでは、SpursEngine用のWindows向けコンソール版H264エンコーダやAviUtlプラグイン版エンコーダが公開されています。ビットレートを最大値にして量子化行列で圧縮率を調整し、SpursEngineで擬似的に固定量子化のエンコードを行うテクニックを参考にさせていただきました。

がらくたハウスのがらくた置き場の、まじぽか太郎さんがSpursEngine向けに調整された量子化行列を参考にさせていただきました。

サポート

この記事に関するご質問はCell/B.E. & SpursEngine BBSにお願いします。