normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

AWS SDK for Java を使って Elastic Transcoder を弄ってみた

Windows Azure メディアサービスを弄っていたが、ふと http://aws.amazon.com/jp/elastictranscoder/title=AWS Elatic Transcode] を弄る用事があった。せっかくサンプルを書いてみたので公開してみる。
AWS Elastic Transcoder は、AWS が提供する動画変換サービスであり、Windows Azure メディアサービスと同様にクラウドリソースを利用して動画を変換することができる。また、動画等の大容量ファイルは S3 に格納することができるため、これまたクラウドリソースを有効活用することができる。

ちなみに以下のブログを大変参考にさせて頂いたので、本稿を読み進める前に是非参考にしていただきたい

AWS SDK for Java のセットアップ

まずは以下の pom.xml を作成する。

<?xml version="1.0" encoding="UTF-8"?>
<project
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.mydomain</groupId>
	<artifactId>elastic-transcoder-sample</artifactId>
	<version>0.9.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>AWS Elastic Transcoder Sample</name>
	<description>AWS Elastic Transcoder用のサンプル</description>

	<dependencies>
		<dependency>
			<groupId>com.amazonaws</groupId>
			<artifactId>aws-java-sdk</artifactId>
			<version>1.5.4</version>
		</dependency>
	</dependencies>

</project>

上記の xml 作成後、「mvn eclipse:eclipse」コマンドを実行することで AWS SDK for Java を利用可能な Eclipse プロジェクトを初期化できる。
今回利用するのは Elastic Transcoder の機能のみだが、AWS SDK for Java には Elastic Transcoder 以外の AWS サービスを利用可能な機能も含まれている。

Elastic Transcoder を利用する Java コード

次に 依存 jar の参照を解決後、以下のコードを利用して Elastic Transcoder に対して処理を行う。今回作成した処理は「パイプラインの一覧表示」「プリセットの一覧表示」「エンコーディングのジョブ生成」「カスタムプリセットの登録」だ。

package com.mydomain;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider;
import com.amazonaws.services.elastictranscoder.AmazonElasticTranscoder;
import com.amazonaws.services.elastictranscoder.AmazonElasticTranscoderClient;
import com.amazonaws.services.elastictranscoder.model.AudioParameters;
import com.amazonaws.services.elastictranscoder.model.CreateJobOutput;
import com.amazonaws.services.elastictranscoder.model.CreateJobRequest;
import com.amazonaws.services.elastictranscoder.model.CreateJobResult;
import com.amazonaws.services.elastictranscoder.model.CreatePresetRequest;
import com.amazonaws.services.elastictranscoder.model.Job;
import com.amazonaws.services.elastictranscoder.model.JobInput;
import com.amazonaws.services.elastictranscoder.model.JobOutput;
import com.amazonaws.services.elastictranscoder.model.ListJobsByPipelineRequest;
import com.amazonaws.services.elastictranscoder.model.ListJobsByPipelineResult;
import com.amazonaws.services.elastictranscoder.model.ListPipelinesRequest;
import com.amazonaws.services.elastictranscoder.model.ListPipelinesResult;
import com.amazonaws.services.elastictranscoder.model.ListPresetsRequest;
import com.amazonaws.services.elastictranscoder.model.ListPresetsResult;
import com.amazonaws.services.elastictranscoder.model.Pipeline;
import com.amazonaws.services.elastictranscoder.model.Preset;
import com.amazonaws.services.elastictranscoder.model.PresetWatermark;
import com.amazonaws.services.elastictranscoder.model.Thumbnails;
import com.amazonaws.services.elastictranscoder.model.VideoParameters;

// Elastic Transcoder の AWS 上公式ドキュメント
// http://docs.aws.amazon.com/elastictranscoder/latest/developerguide/introduction.html
public class AmazonElasticTranscoderSample {

	public static void main(String[] args) throws Exception {
		AmazonElasticTranscoder transCoder = init();
		//dispPresetList(transCoder);
		//createCustomPreset(transCoder);
		createJobEncodeMp4ToMp4(transCoder);
		System.out.println("終了");
	}

	// Elastic TransCoder を制御するインスタンスを生成
	static AmazonElasticTranscoder init() throws Exception {
		AWSCredentials credentials = new ClasspathPropertiesFileCredentialsProvider()
				.getCredentials();

		ClientConfiguration conf = new ClientConfiguration();
		try {
			// プロパティ情報から認証プロキシ情報を読み取る
			Properties prop = new Properties();
			prop.load(new InputStreamReader(AmazonElasticTranscoderSample.class
					.getResourceAsStream("/ProxySetting.properties")));
			conf.setProxyHost(prop.getProperty("PROXY_HOST"));
			conf.setProxyPort(Integer.valueOf(prop.getProperty("PROXY_PORT")));
			conf.setProxyUsername(prop.getProperty("PROXY_USERNAME"));
			conf.setProxyPassword(prop.getProperty("PROXY_PASSWORD"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		AmazonElasticTranscoder transCoder = new AmazonElasticTranscoderClient(
				credentials, conf);

		// 利用しているリージョンのエンドポイントを設定
		// ここを間違えると何も表示されない
		transCoder
				.setEndpoint("https://elastictranscoder.ap-northeast-1.amazonaws.com");
		return transCoder;
	}

	// 指定したエンドポイントに登録されたプリセットを表示する
	public static void dispPresetList(AmazonElasticTranscoder transCoder) {
		System.out.println("----------Preset List----------");
		ListPresetsRequest listPresetsRequest = new ListPresetsRequest();
		ListPresetsResult listPresetsResult = transCoder
				.listPresets(listPresetsRequest);
		List<Preset> presets = listPresetsResult.getPresets();
		for (Preset preset : presets) {
			System.out.println("Id : " + preset.getId());
			System.out.println("  Name : " + preset.getName());
			System.out.println("  Description : " + preset.getDescription());
			System.out.println("  Type : " + preset.getType());
			System.out.println("  Thumbnails : " + preset.getThumbnails());
			System.out.println("  Video : " + preset.getVideo());
			System.out.println("  Audio : " + preset.getAudio());
		}
	}

	// パイプラインのリストを表示
	public static void dispPiplineList(AmazonElasticTranscoder transCoder) {
		ListPipelinesRequest listPipelineRequest = new ListPipelinesRequest();
		ListPipelinesResult listPipelineResult = transCoder
				.listPipelines(listPipelineRequest);
		List<Pipeline> pipelines = listPipelineResult.getPipelines();
		System.out.println("----------Pipeline List----------");
		for (Pipeline pipeline : pipelines) {
			System.out.println("Id : " + pipeline.getId());
			System.out.println("  Name : " + pipeline.getName());
			System.out.println("  Role : " + pipeline.getRole());
			ListJobsByPipelineRequest listJobsByPipelineRequest = new ListJobsByPipelineRequest();
			listJobsByPipelineRequest.setPipelineId(pipeline.getId());
			ListJobsByPipelineResult listJobsByPipelineResult = transCoder
					.listJobsByPipeline(listJobsByPipelineRequest);
			List<Job> jobs = listJobsByPipelineResult.getJobs();
			for (Job job : jobs) {
				System.out.println("  Id : " + job.getId());
				JobInput jobInput = job.getInput();
				System.out.println("    JobInput");
				System.out.println("      AspectRatio : "
						+ jobInput.getAspectRatio());
				System.out.println("      Container : "
						+ jobInput.getContainer());
				System.out.println("      FrameRate : "
						+ jobInput.getFrameRate());
				System.out.println("      Interlaced : "
						+ jobInput.getInterlaced());
				System.out.println("      Key : " + jobInput.getKey());
				System.out.println("      Resolution : "
						+ jobInput.getResolution());
				JobOutput jobOutput = job.getOutput();
				System.out.println("    JobOutput");
				System.out.println("      Key : " + jobOutput.getKey());
				System.out.println("      PresetId : "
						+ jobOutput.getPresetId());
				System.out.println("      Rotate : " + jobOutput.getRotate());
				System.out.println("      Status : " + jobOutput.getStatus());
				System.out.println("      StatusDetail : "
						+ jobOutput.getStatusDetail());
				System.out.println("      ThumbnailPattern : "
						+ jobOutput.getThumbnailPattern());
			}
		}
	}

	// mp4 から mp4 に変換する
	public static void createJobEncodeMp4ToMp4(
			AmazonElasticTranscoder transCoder) {
		String piplineId = "";
		String presetId = "";
		try {
			// プロパティ情報から認証プロキシ情報を読み取る
			Properties prop = new Properties();
			prop.load(new InputStreamReader(AmazonElasticTranscoderSample.class
					.getResourceAsStream("/AppSetting.properties")));
			piplineId = prop.getProperty("PIPLINE_ID");
			presetId = prop.getProperty("PRESET_ID");
		} catch (IOException e) {
			e.printStackTrace();
		}

		System.out.println("---------- Create Job ----------");
		CreateJobRequest createJobRequest = new CreateJobRequest();
		createJobRequest.setPipelineId(piplineId);
		JobInput input = new JobInput();
		input.setKey("WP_20130222_011.mp4");
		input.setAspectRatio("auto");
		input.setContainer("auto");
		input.setFrameRate("auto");
		input.setInterlaced("auto");
		input.setResolution("auto");
		createJobRequest.setInput(input);
		createJobRequest.setOutputKeyPrefix("p-transoder/");

		List<CreateJobOutput> outputs = new ArrayList<CreateJobOutput>();
		CreateJobOutput output1 = new CreateJobOutput();
		output1.setKey("mp4/sample.mp4");
		output1.setPresetId(presetId);
		output1.setThumbnailPattern("mp4/thumb-{count}");
		output1.setRotate("auto");

		outputs.add(output1);

		createJobRequest.setOutputs(outputs);

		CreateJobResult createJobResult = transCoder
				.createJob(createJobRequest);
		com.amazonaws.services.elastictranscoder.model.Job job = createJobResult
				.getJob();
		System.out.println("Name : " + job.getStatus());
		System.out.println("Id : " + job.getId());
		System.out.println("Output : " + job.getOutput());
	}

	// カスタムプリセットの作成
	public static void createCustomPreset(AmazonElasticTranscoder transCoder) {
		CreatePresetRequest request = new CreatePresetRequest();

		request.setContainer("mp4");

		AudioParameters audio = new AudioParameters();
		audio.setBitRate("128");
		audio.setChannels("2");
		audio.setCodec("AAC");
		audio.setSampleRate("44100");
		request.setAudio(audio);
		request.setDescription("preset created from sdk");
		request.setName("Preset created from AWS SDK");

		Thumbnails thumbnails = new Thumbnails();
		thumbnails.setFormat("png");
		thumbnails.setInterval("300");
		thumbnails.setMaxWidth("192");
		thumbnails.setMaxHeight("108");
		thumbnails.setSizingPolicy("ShrinkToFit");
		thumbnails.setPaddingPolicy("NoPad");
		request.setThumbnails(thumbnails);

		VideoParameters video = new VideoParameters();
		video.setCodec("H.264");
		Map<String, String> codecOptions = new HashMap<>();
		codecOptions.put("MaxReferenceFrames", "1");
		codecOptions.put("Profile", "baseline");
		codecOptions.put("Level", "3");
		video.setCodecOptions(codecOptions);
		video.setKeyframesMaxDist("90");
		video.setFixedGOP("true");
		video.setBitRate("272");
		video.setFrameRate("auto");
		video.setMaxWidth("400");
		video.setMaxHeight("288");
		video.setDisplayAspectRatio("auto");
		video.setSizingPolicy("ShrinkToFit");
		video.setPaddingPolicy("NoPad");

		//この辺は手抜き(汗
		{
			Collection<PresetWatermark> watermarks = new ArrayList<>();

			PresetWatermark watermark;
			watermark = new PresetWatermark();
			watermark.setId("TopLeft");
			watermark.setMaxWidth("10%");
			watermark.setMaxHeight("10%");
			watermarks.add(watermark);

			video.setWatermarks(watermarks);
		}

		request.setVideo(video);

		transCoder.createPreset(request);
	}
}

別途で以下 3つのプロパティファイルを作成している点に注意してほしい。

  • AwsCredential.properties(AWS のサービスを利用する場合に必須)
  • AppSetting.properties(Elastic Transcoder の piplieID とかを外だししたので、実際作成する場合は必須でない)
  • ProperSetting.properties(認証プロキシ情報の外だし用、実際作成する場合は必須でない)