2倍速動画の作成方法

スマートフォンをGalaxy S2 (SC-02C)からGalaxy S3 (SC-06D)へ機種変更しました。Xi、おサイフケータイに対応したことは良かったのですが、Androidで唯一2倍速再生できる動画プレイヤーであるdiceplayerが使えなくなったのには困りました。
チップセットの関係か、動画のフォーマットをh264 mp4からmkvやaviなどへ変えても、2秒程再生するとフリーズしてしまうという状況は変わりませんでした。
そこで苦肉の策として動画そのものを2倍速に再エンコードし、他の動画プレイヤーで再生することにしました。

用意するもの

以下はQSV(Quick Sync Video)対応のCPU使用時に処理を高速化したいときだけ必要

環境構築

携帯動画変換君の設定ファイルを作成。

Transcoding_GalaxyS3.ini
[Info]
Title= 2 倍速

[Item0]
Title= 2 倍速 AVI/16:9 mp4
Command0=""<%AppPath%>\cores\ffmpeg" -y -i "<%InputFile%>" -s 640x360 -r 14.99 "<%TemporaryFile%>.yuv" -acodec pcm_s16le -ac 2 -ar 48000 "<%TemporaryFile%>.wav""
Command1=""<%AppPath%>\cores\ffmpeg" -y -s 640x360 -r 29.97 -i "<%TemporaryFile%>.yuv" -bitexact -an -vcodec h264 -b 500 -s 640x360 -r 29.97 -sameq -f mp4 "<%TemporaryFile%>_1.mp4""
Command2=""<%AppPath%>\cores\sox" "<%TemporaryFile%>.wav" "<%TemporaryFile%>_1.wav" tempo 2.0 30"
Command3=""<%AppPath%>\cores\ffmpeg" -y -i "<%TemporaryFile%>_1.wav" -bitexact -acodec mp3 -ac 2 -ar 48000 -ab 128 -f mp3 "<%TemporaryFile%>.mp3"" 
Command4=""<%AppPath%>\cores\mp4box" -add "<%TemporaryFile%>_1.mp4"#video -add "<%TemporaryFile%>.mp3"#audio -new "<%OutputFile%>_x2.mp4"" 
Command5="cmd /c "del "<%TemporaryFile%>*.*"""

[Item1]
Title= 2 倍速 AVI/16:9 mp4 qsv
Command0=""<%AppPath%>\cores\ffmpeg" -y -i "<%InputFile%>" -s 640x360 -r 14.99 "<%TemporaryFile%>.yuv" -acodec pcm_s16le -ac 2 -ar 48000 "<%TemporaryFile%>.wav""
Command1=""<%AppPath%>\cores\QSVEncC" --input-res 640x360 --fps 29.97 -i "<%TemporaryFile%>.yuv" -o "<%TemporaryFile%>.264""
Command2=""<%AppPath%>\cores\sox" "<%TemporaryFile%>.wav" "<%TemporaryFile%>_1.wav" tempo 2.0 30"
Command3=""<%AppPath%>\cores\ffmpeg" -y -i "<%TemporaryFile%>_1.wav" -bitexact -acodec mp3 -ac 2 -ar 48000 -ab 128 -f mp3 "<%TemporaryFile%>.mp3"" 
Command4=""<%AppPath%>\cores\mp4box" -add "<%TemporaryFile%>.264"#video -add "<%TemporaryFile%>.mp3"#audio -new "<%OutputFile%>_x2.mp4"" 
Command5="cmd /c "del "<%TemporaryFile%>*.*"""

[Item2]
Title= 2 倍速 AVI/16:9 mp4 qsv core2最適化
Command0=""<%AppPath%>\cores\ffmpeg_core2_20120904" -y -i "<%InputFile%>" -s 640x360 -r 14.99 "<%TemporaryFile%>.yuv" -acodec pcm_s16le -ac 2 -ar 48000 "<%TemporaryFile%>.wav""
Command1=""<%AppPath%>\cores\QSVEncC" --input-res 640x360 --fps 29.97 --gop-len 30 --strict-gop -i "<%TemporaryFile%>.yuv" -o "<%TemporaryFile%>.264""
Command2=""<%AppPath%>\cores\sox" "<%TemporaryFile%>.wav" "<%TemporaryFile%>_1.wav" tempo 2.0 30"
Command3=""<%AppPath%>\cores\ffmpeg_core2_20120904" -y -i "<%TemporaryFile%>_1.wav"  -acodec aac -strict -2 -ac 2 -ar 48000 -ab 128k "<%TemporaryFile%>.aac"" 
Command4=""<%AppPath%>\cores\mp4box" -add "<%TemporaryFile%>.264"#video -add "<%TemporaryFile%>.aac"#audio -new "<%OutputFile%>_x2.mp4"" 
Command5="cmd /c "del "<%TemporaryFile%>*.*"""

sox.exe QSVEncC.exe MP4Box.exe ffmpeg_core2_20120904.exe を 3GP_Converter034\cores へコピー。

字幕ファイル(srt)もタイムスタンプを変更し2倍速へ対応しないといけないので、変換するスクリプトを作成しました。動作にはPerlが必要です。

srt_x2.bat
@echo off

set output=E:\TS-encoded\2倍速
set perl=C:\Dwimperl\perl\bin\perl.exe
set srt_x2="E:\ts-encoded\srt_x2.pl"

for %%a in (%*) do (
	%perl% %srt_x2% %%a "%output%\%%~na_x2.srt"
)


echo 処理したファイル
for %%a in (%*) do (
	echo %%a
	  for %%I in ("%output%\%%~na_x2.srt") do if %%~zI equ 3 (
	      rem .srt のファイルサイズが 3bytes の場合
	      del %%I
	      echo   deleted
	  )
)

pause
srt_x2.pl
use strict;

my $file = $ARGV[0];
my $output_file = $ARGV[1];

my @lines;

open FILE, $file or die "can't open file: $file";
while (<FILE>) {
	chomp;
	if (/^(..):(..):(..),(...) --> (..):(..):(..),(...)$/) {
		# 数字の変更
		
		# 開始時刻
		my $hh = $1;
		my $mm = $2;
		my $ss = $3;
		my $msec = $4;

		my $start = ($hh*3600 + $mm*60 + $ss)*1000 + $msec;
		$start = int ($start / 2);
		
		$hh = int ($start/3600/1000);
		$mm = int (($start/1000 - $hh*3600)/60);
		$ss = int (($start/1000 - $hh*3600 - $mm*60));
		$msec = $start - ($hh*3600 + $mm*60 + $ss)*1000;

		$start = sprintf("%02d:%02d:%02d,%03d", $hh, $mm, $ss, $msec);
		
		# 終了時刻
		$hh = $5;
		$mm = $6;
		$ss = $7;
		$msec = $8;
		
		my $end = ($hh*3600 + $mm*60 + $ss)*1000 + $msec;
		$end = int ($end / 2);
		
		$hh = int ($end/3600/1000);
		$mm = int (($end/1000 - $hh*3600)/60);
		$ss = int (($end/1000 - $hh*3600 - $mm*60));
		$msec = $end - ($hh*3600 + $mm*60 + $ss)*1000;

		$end = sprintf("%02d:%02d:%02d,%03d", $hh, $mm, $ss, $msec);
		
		push @lines, "$start --> $end";		
	} else {
		# 外字の変換 [外:43856FD7C04A779E571FE24C47F02A6C] → [外]
		s/\[\:.+?\]/[外]/g;
		push @lines, $_;
	}
}
close FILE;

open OUTPUT, ">$output_file" or die "can't open output file: $output_file";
print OUTPUT join("\n", @lines);
close OUTPUT;

使用方法

  1. 任意の動画を640x360にエンコード
  2. 携帯動画変換君へファイルをドラッグ&ドロップ
  3. 字幕ファイル(動画ファイル名.srt)があれば srt_x2.bat へドラッグ&ドロップ

(A)2 倍速 AVI/16:9 mp4、(B)2 倍速 AVI/16:9 mp4 qsv、(C)2 倍速 AVI/16:9 mp4 qsv core2最適化の設定があります。(A)はソフトウェアエンコード、(B)(C)はハードウェアエンコード(QSV対応のCPUの場合のみ)、(C)はcore2以降のCPUに最適化されたffmpegでマルチスレッド処理もできて高速です。

参考までにcorei7 2600kの環境で60分の動画処理にかかった時間は、(A)12:42、(B)6:02、(C)4:42でした。QSVの効果(mp4エンコードのみ)は約6倍、core2最適化ffmpegの効果(demux処理のみ)は約2倍です。


(A)2 倍速 AVI/16:9 mp4

  1. demux 3:11 (3:11)
  2. mp4 11:00 (6:49)
  3. mp3 12:07 (1:07)
  4. mp4box 12:42 (0:35)

(B)2 倍速 AVI/16:9 mp4 qsv

  1. demux 3:14 (3:14)
  2. mp4 4:20 (1:06)
  3. mp3 5:28 (1:08)
  4. mp4box 6:02 (0:34)

(C)2 倍速 AVI/16:9 mp4 qsv core2最適化

  1. demux 1:38 (1:38)
  2. mp4 2:48 (1:10)
  3. mp3 3:55 (1:07)
  4. mp4box 4:42 (0:47)