normalian blog

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

WebLogic Server 12c を Windows Azure の Windows Server 2012 R2 で動かしてみる

既に既知の情報かと思うが、Microsoft と Oracle が連携したことで Windows Azure 上で WebLogicOracle DB を利用することが可能となった。これらの一連の情報については、SATO NAOKI氏が以下にまとめている。
Oracle OpenWorld 2013: Oracleのミッション クリティカル ソフトウェアと、Microsoftのエンタープライズ級クラウド

JDK6, JDK7 がインストールされただけの Windows Server 2012 インスタンスを作成することも可能であり、以下のような組み合わせでも Oracle ラインセンスのプロダクトを利用可能だ。

WebLogic Server 12c on Windows Server 2012 R2&Windows Azure な手順メモ

SATO NAOKI 氏の記事に記載されたリンクから、Windows Azure 上で WebLogicOracle Linux 上で動作させる手順が記載されたPDFは入手することが可能だ。しかし、Windows Server 上で WebLogic を動作させる

WebLogic Server 12c を Windows Azure の Windows Server 2012 R2 で動かす

今後は SQL Database への接続やクラスタリング構成を試してみたい。

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(認証プロキシ情報の外だし用、実際作成する場合は必須でない)

Windows Azure メディアサービスでバージョンを指定して MediaProcessor を取得する方法

Window Azure メディアサービスでは、用意されたエンコーダやエンクリプタを利用して、動画のエンコーディングや暗号化が可能だ。今回はサンプルコードベースでバージョンを指定した MediaProcessor の取得方法を紹介する。

サンプルコードと実行結果

さっそくサンプルコードを紹介する。NuGet から Windows Azure Media Service のSDKを取得後、以下のコードを作成する

using Microsoft.WindowsAzure.MediaServices.Client;
using System;
using System.IO;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudMediaContext context = new CloudMediaContext("<アカウント名>", "<アカウントキー>");

            Console.WriteLine("Media Processor 一覧");
            foreach (var mediaProcessor in context.MediaProcessors)
            {
                Console.WriteLine(string.Join(",", new object[]{
                    mediaProcessor.Id,
                    mediaProcessor.Name,
                    mediaProcessor.Vendor,
                    mediaProcessor.Version
                }));
            }
            Console.WriteLine("");

            // OrderBy 内の Version 操系で NotSupportedException がでるので、直前で ToList()
            Console.WriteLine("最新の Windows Azure Media Encoder だけ取得");
            var mediaEncoderVerCurrent = context.MediaProcessors.ToList()
                .OrderByDescending(wame => new Version(wame.Version)).FirstOrDefault();
            Console.WriteLine(string.Join(",", new object[]{
                    mediaEncoderVerCurrent.Id,
                    mediaEncoderVerCurrent.Name,
                    mediaEncoderVerCurrent.Vendor,
                    mediaEncoderVerCurrent.Version
                }));
            Console.WriteLine("");

            Console.WriteLine("特定の Windows Azure Media Encoder だけ取得");
            // OrderBy 内の Version 操系で NotSupportedException がでるので、直前で ToList()
            var mediaEncoderVer23 = context.MediaProcessors.ToList()
                .FirstOrDefault(wame => new Version(wame.Version) == new Version("2.3"));
            Console.WriteLine(string.Join(",", new object[]{
                    mediaEncoderVer23.Id,
                    mediaEncoderVer23.Name,
                    mediaEncoderVer23.Vendor,
                    mediaEncoderVer23.Version
                }));
            Console.ReadKey();
        }
    }
}

上記の実行結果は以下となる。エンコーダやエンクリプタの他、ストレージの複合化やパッケージング用の Media Processor もあるらしい。この辺りは Process Assets with the Media Services SDK for .NET - Accessing a Media Processor を参照してほしい。

Media Processor 一覧
nb:mpid:UUID:70bdc2c3-ebf4-42a9-8542-5afc1e55d217,Windows Azure Media Encoder,Microsoft,2.3
nb:mpid:UUID:38a620d8-b8dc-4e39-bb2e-7d589587232b,Windows Azure Media Encryptor,Microsoft,2.4
nb:mpid:UUID:aec03716-7c5e-4f68-b592-f4850eba9f10,Storage Decryption,Microsoft,1.7
nb:mpid:UUID:a2f9afe9-7146-4882-a5f7-da4a85e06a93,Windows Azure Media Packager,Microsoft,2.4
nb:mpid:UUID:2e7aa8f3-4961-4e0c-b4db-0e0439e524f5,Windows Azure Media Encoder,Microsoft,3.1

最新の Windows Azure Media Encoder だけ取得
nb:mpid:UUID:2e7aa8f3-4961-4e0c-b4db-0e0439e524f5,Windows Azure Media Encoder,Microsoft,3.1

特定の Windows Azure Media Encoder だけ取得
nb:mpid:UUID:70bdc2c3-ebf4-42a9-8542-5afc1e55d217,Windows Azure Media Encoder,Microsoft,2.3

Windows Azure Media Services .NET SDK 2.3.0.0 の変更 - 通知APIに Queue ストレージを利用編

前回の記事で id:waritohutsu:20130715:1373856716 複数のストレージアカウントをアタッチする方法を紹介したが、今回は主要更新の一つである通知APIに Queue ストレージを利用する方法を紹介する。詳細な手順やサンプルコード全体は Listening to Windows Azure Media Services Notifications に記載されているため、本記事を通読後に一読することをお勧めする。
現時点でのQueue ストレージを利用した通知APIの考慮点は以下になる。

通知APIでQueue ストレージを利用する

まず、Media Service の通知結果を格納するためのストレージサービスを作成する。同ストレージサービスは Media Service にアタッチされているものでも構わない。以下に実行結果も含めたスクリーンキャプチャなので、構成の参考にしてほしい。

次に、Media Service SDK .NET版を利用した以下の様なC#コード(抜粋で恐縮だが)を作成する。

private static IJob EncodeToMp4(CloudMediaContext context, string inputAssetId)
{

    var inputAsset = context.Assets.Where(a => a.Id == inputAssetId).FirstOrDefault();
    if (inputAsset == null)
        throw new ArgumentException("Could not find assetId: " + inputAssetId);

    var encodingPreset = "H264 Adaptive Bitrate MP4 Set SD 16x9";

    IJob job = context.Jobs.Create("Encoding " + inputAsset.Name + " to " + encodingPreset);

    //通知に利用する方法(Queueストレージ)とエンドポイント(myqueue)を指定
    INotificationEndPoint notificationEndPoint = context.NotificationEndPoints.Create(
            Guid.NewGuid().ToString(), NotificationEndPointType.AzureQueue, "myqueue");

    //全てのイベント(Schduled -> processing -> finished)で通知を行うことを設定
    //job.JobNotificationSubscriptions.AddNew(NotificationJobState.FinalStatesOnly, notificationEndPoint);
    job.JobNotificationSubscriptions.AddNew(NotificationJobState.All, notificationEndPoint);

    IMediaProcessor latestWameMediaProcessor = (from p in context.MediaProcessors where p.Name == "Windows Azure Media Encoder" select p).ToList()
                                                                 .OrderBy(wame => new Version(wame.Version)).LastOrDefault();

    ITask encodeTask = job.Tasks.AddNew("Encoding", latestWameMediaProcessor, encodingPreset, TaskOptions.None);

    encodeTask.InputAssets.Add(inputAsset);
    encodeTask.OutputAssets.AddNew(inputAsset.Name + " as " + encodingPreset, AssetCreationOptions.None);

    job.StateChanged += new EventHandler<JobStateChangedEventArgs>(JobStateChanged);
    job.Submit();
    job.GetExecutionProgressTask(CancellationToken.None).Wait();

    return job;
}

現時点では NotificationEndPointType.AzureQueue しか通知の方法が用意されていないが、今後は通知方法の拡張が期待される。また、通知情報は"完了時のみ(NotificationJobState.FinalStatesOnly)" or "イベント毎の通知(NotificationJobState.All)" or "通知しない(NotificationJobState.None)" を選択が可能だ。

上記のコードを含めた処理を実行した結果、以下のJSON形式の文字列がQueueストレージに格納される。「1.登録 → 2.スケジュール → 3.処理中 → 4.完了」の流れが格納されていることが確認できる。

{"MessageVersion":"1.0","EventType":"NotificationEndPointRegistration","ETag":"a756c1f67e96d95273e38e5e5e918a77cbef37bdfaded6069eb0a8bd800bae81","TimeStamp":"2013-07-21T02:08:04","Properties":{"NotificationEndPointId":"nb:nepid:UUID:4e4199b8-3db1-43ea-851b-95576d17e60b","State":"Registered","Name":"8822be8d-2791-4ad0-a991-54ef1b74388a","Created":"2013-07-21T02:08:01"}}

{"MessageVersion":"1.0","EventType":"JobStateChange","ETag":"f9cb50428bc9927d4f637d8efe9a82aa3de0c65ded214cde17ef378d5388e218","TimeStamp":"2013-07-21T02:08:17","Properties":{"JobId":"nb:jid:UUID:10a68b86-fe65-b943-bd2d-6ad2ba1cd3aa","JobName":"Encoding azure to H264 Adaptive Bitrate MP4 Set SD 16x9","NewState":"Scheduled","OldState":"Queued","AccountName":"xxxxxxxxxxxxxxxxxxx"}}

{"MessageVersion":"1.0","EventType":"JobStateChange","ETag":"b70613d1c78821f96a05bda3c7ec16623424441ecd37b0b9417cbaa70761faab","TimeStamp":"2013-07-21T02:08:22","Properties":{"JobId":"nb:jid:UUID:10a68b86-fe65-b943-bd2d-6ad2ba1cd3aa","JobName":"Encoding azure to H264 Adaptive Bitrate MP4 Set SD 16x9","NewState":"Processing","OldState":"Scheduled","AccountName":"xxxxxxxxxxxxxxxxxxx"}}

{"MessageVersion":"1.0","EventType":"JobStateChange","ETag":"74830e61be956a9c7566585d09dec148365806b42b9813405d4f97a1e1b3861a","TimeStamp":"2013-07-21T02:09:36","Properties":{"JobId":"nb:jid:UUID:10a68b86-fe65-b943-bd2d-6ad2ba1cd3aa","JobName":"Encoding azure to H264 Adaptive Bitrate MP4 Set SD 16x9","NewState":"Finished","OldState":"Processing","AccountName":"xxxxxxxxxxxxxxxxxxx"}}

下記のJSONオブジェクトを利用する場合は個別にクラスを作成する必要があるので、以下どちらかの手法を利用してほしい。

また、キューストレージのエンドポイントが不正な形式の場合、以下のレスポンスが帰ってくるので参考にしてほしい。

"<?xml version=\"1.0\" encoding=\"utf-8\"?><m:error xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"><m:code /><m:message xml:lang=\"en-US\">NotificationEndPoint.EndPointAddress must match rules described in http://msdn.microsoft.com/en-us/library/windowsazure/dd179349.aspx</m:message></m:error>"

Windows Azure Media Services .NET SDK 2.3.0.0 の変更 - 複数のストレージアカウントをアタッチ編

2013/7/1 に NuGet にて Windows Azure Media Service 2.3.0.0 がリリースされた。今回のリリースにおける主要な更新は以下となる。

こちらの メディア with Microsoft - Windows Azure Media Services .NET SDK 2.3.0.0 の更新 記事にも SDK 2.3.0.0 の更新内容がまとまっているので、別途参照して頂きたい。

複数のストレージアカウントをアタッチする方法

サーバ側には複数のストレージアカウントをアタッチする機能が追加されたが、現時点(2013/7/15)では管理ポータルにも.NET SDK にも本機能を利用するインターフェースは用意されておらず、REST API を利用することによってのみ本機能が利用可能だ。
そのため、今回はHow to: Use Media Services Management REST API に記載されたクラスを参考にしてREST API を操作するコードを以下のように作成する。

ManagementRESTAPIHelper helper =
new ManagementRESTAPIHelper("https://management.core.windows.net",
    "<証明書のThumbprintを記載。管理ポータルを参照のこと>",
    "<上記の証明書に紐づいたサブスクリプションID。同じく管理ポータルを参照のこと>");

// Initialize the AccountInfo class.
MediaServicesAccountInfo accountInfo = new MediaServicesAccountInfo();
accountInfo.MediaServicesAccountName = "<メディアサービスのアカウント名>";
accountInfo.Region = "<メディアサービスを作成したリージョン例:East Asia>";
accountInfo.StorageAccountName = "<ストレージサービスにアタッチしたストレージアカウント名>";
accountInfo.StorageAccountKey = "<ストレージサービスにアタッチしたストレージアカウントのキー>";
accountInfo.BlobStorageEndpoint = "<BLOBストレージのエンドポイント 例:http://xxxxxxxxxxxxxxx.blob.core.windows.net/>";

var storageAccount = new AttachStorageAccountRequest()
{
StorageAccountName = "<アタッチしたいストレージアカウント名>",
StorageAccountKey = "<アタッチしたいストレージアカウントのキー>",
BlobStorageEndpointUri = "<アタッチしたいBLOBストレージのエンドポイント>"
};

Call one of the public methods and attach storage account to media service 
helper.AttachStorageAccountToMediaServiceAccount(accountInfo, storageAccount);

内部では直接REST API を叩いているため、特に Media Service SDK を取得しなくても操作は可能だ。上記のパラメータのうち、証明書に関する情報を取得する方法を以下に図でまとめたので参考にしてほしい。

次に、上記のコードをコンソールアプリケーション等で実行する。処理が正常に実行された場合は以下のメッセージが表示される(別に parimary key が再生成された様子はないがなんでだろう?)。

The primary key was regenerated.

また、すでに自身のメディアサービスにアタッチ済みのストレージアカウントを再アタッチしようとした場合は System.Net.WebException が発生し、以下のメッセージが返される。

{"リモート サーバーがエラーを返しました: (409) 競合"}

System.Net.WebException.Response.StatusCode は System.Net.HttpStatusCode.Conflict で返ってくるので、必要ならば参考にしてほしい。

REST API の処理が完了した後、数十秒後(直後では反映されていなかった)に以下のコードを実行するとメディアサービスに複数のストレージサービスがアタッチされていることが確認できる。また以下のコードは Media Service .NET SDK を利用している。

CloudMediaContext context = new CloudMediaContext("<メディアサービスのアカウント名>", "<メディアサービスのキー名>");

foreach (var account in context.StorageAccounts)
{
Console.WriteLine("Name={0}, IsDefault={1}", account.Name, account.IsDefault);
}

実行結果は以下となる(二つのストレージアカウントを紐づけた後に上記のコードを実行した)。最初にメディアサービスに紐づけたストレージアカウントがデフォルトとして扱われる点に注意してほしい。

Name=xxxxxxmediaservicestorage1, IsDefault=False
Name=xxxxxxmediaservicestorage2, IsDefault=True
Name=xxxxxxmediaservicestorage3, IsDefault=False

参考

Windows版のFirefoxは ver.21 からデフォルトで H.264形式動画が再生可能に

今回は Windows Azure Media Service をいじっていて得た Windows版 Firefox に関する情報を備忘録として記載する。
実は Windows 版に限るが、FirefoxH.264 動画再生については以下の環境になっている様だ

さっそく Firefox ver.22 × Windows 8 で動作検証

以下のコードを利用し、Firefox ver.22 で H.264 動画を再生した。

<!DOCTYPE HTML>
<html>
<head>
<title>サンプルページ</title>
</head>
<body>
<h2>動画</h2>
<video style="width:400pt;" src="mymovie.mp4" controls></video>
</body>
</html>

配置したのは H.264 の動画のみでありOGGやWebM系の動画は配置していないが、以下の様に動画再生が可能だった。

HTML5 な動画再生については…

まだ色々ありますな(汗

MultiTouch Behavior を利用して Silverlight でゼスチャー操作をしてみる

今回は SilverlightWPF に対して ゼスチャー操作を利用可能にする MultiTouch Behavior について紹介する。

MultiTouch Behavior のインストール

MultiTouch Behavior パッケージは NuGet で利用可能であり、パッケージマネージャコンソールで以下のコマンドを入力することで利用可能になる。

PM> Install-Package MultiTouchBehaviors 

といいつつ、まだまだバージョンは 0.6.9 な辺りでどうなんだろうかと思ったり(汗。インストールして確認したところ、どうやら Silverlight 4 向けにビルドされたらしく Silverlight 5 では利用できなかった。。。。
仕方がないので CodePlex - Windows Phone, Silverlight and WPF Multi-Touch Manipulations から最新版のソースコードを取得し、Silverlight 5 向けにビルドしなおすことで MultiTouch Behavior を Silverlight 5 でも利用可能となった。

MultiTouch Behavior を利用したアプリケーソン

特にこだわりがなければ、まずは一旦 Silverlight 4 アプリケーションを新規に作成し、NuGet を利用して MultiTouch Behavior をインストールする。更に、 XAML を以下のように書き換えて Silverlight アプリケーションを起動する。

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:behaviors="clr-namespace:MultiTouch.Behaviors.Silverlight4;assembly=MultiTouch.Behaviors.Silverlight4"
    xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    mc:Ignorable="d"
    d:DesignHeight="600" d:DesignWidth="800">

    <Grid x:Name="LayoutRoot" Background="White">
        <Canvas>
            <Image Source="Images/P1000555.JPG" Width="675" Canvas.Left="61" Canvas.Top="43" Height="506">
                <interactivity:Interaction.Behaviors>
                    <behaviors:MultiTouchBehavior IsRotateEnabled="True" IsScaleEnabled="True" 
                                              MinimumScale="100" MaximumScale="500"  />
                </interactivity:Interaction.Behaviors>
            </Image>
        </Canvas>
    </Grid>
</UserControl>

アプリケーション後、回転・拡大・移動のゼスチャ操作を行うことが可能となる。

また、ソースコード内を確認したところ、Touch系のイベントが存在しない PC向け Silverlight は、マウス系のイベントを美味く利用して対応しているようだ。興味のある方はソースコードを参照しても良いだろう。

参考サイト

利用可能な操作等々は以下の動画を参考にして頂ければよいだろう。