Azure Media Indexer と Microsoft Translator を使って、英語の動画に、日本語字幕を付ける!!

IT関連の最新情報は、どうしても英語のものが多いですよね。英語に行くと、有償セッションのビデオ動画があったりするのですが、日本語のものはどうしても人が翻訳して、映像のシーンを指定して字幕を付けるので、どうしても時間とお金がかかります。結果としては、多くの情報は日本語になりません。
また、日本語と英語、くらいの数の翻訳であればまだいいのですが、フランス語、ドイツ語など増やそうと思ったら大変です。
Azure Media Servicesがそのお手伝いをします。

9月のアップデートの中に、Azure Media Indexerという機能が追加され、サービスインをしました。
動画の中の主に話している「声」を抽出して、テキストのファイルにしてくれます。しかもそのテキストのファイルは、業界標準の字幕のファイルフォーマットそのままだったりしますので、簡単に字幕付きのビデオプレイヤーを作成できるのです。TTMLの場合は、声と時間が紐づいていますから、動画を扱う上では大変相性が良いです。

Timed Text Markup Language (TTML):
http://en.wikipedia.org/wiki/Timed_text#Markup_language_specifications

 

 

このサンプルを実行した結果は、このサイトで体験いただけます。

http://dahatakettml.azureedge.net/

※ このサイトは未来永劫動いているわけではありませんので、ご注意ください…

 

出力ファイル

  • 字幕:        TTML or SAMI
  • 音声検索:     SQL Serverのフルテキストサーチ用
  • キーワード:     ビデオの中でのもの

以下、執筆時点の注意点です。

ここでは、TTMLに焦点をあて、ブラウザーベースのHTML5 ビデオプレイヤーを作成します。
実は、TTMLとHTML5 videoタグは大変相性が良く、videoタグの中のtrackタグで、ファイルをそのまま使えるのです!!!

 

Track ElementのW3C標準化の状況:
http://status.modern.ie/trackelement?term=track


IE10以降ですね。今すぐ最新のIE11にしましょう!

 

  1. 作成手順:

以下のフローとなります。

  • 英語のmp4ファイルを準備する
  • Azure Media Indexerにてttml作成
  • Microsoft Translatorにて、英語のttmlを日本語に
  • HTML ページにて、全て参照
  1. 事前準備

 

  1. Microsoft Translatorの契約

Microsoft Azure MarkeplacetからAPI利用をします。

Getting Started with Microsoft Translator:
http://msdn.microsoft.com/en-us/library/hh454949.aspx

  1. Microsoft Azure MarketPlaceのサイトに行き、サインインをします。

    https://datamarket.azure.com/home/

    初めてサインインした場合は、登録画面になりますので、適切な情報を入力し、登録してください。

     

  2. Microsoft Translatorを検索します。画面右上の検索ボックスに”Translator“などと入力して検索してください。

    Microsoft Translatorが表示されます。

     

  3. 契約メニューを選択します。

    Microsoft Translatorは、翻訳文字数に応じて、課金が必要になります。
    ここでは、[無償]のものを選択します。


    ※ 上記画面は、契約済みの場合です。

     

  1. 開発者用キーを作成します。

    Microsoft Azure Marketplace経由でアプリケーション呼び出しをする際には、Client IDClient Secretの2つをもって認証を行います。
    ここでは、それを作成します。

    画面上部の[マイアカウント]を選択して、その後、画面左側に表示されるメニューから[開発者]を選択します。

  2. [開発者]の画面にて、一番下の[登録] を押します。

    1. アプリケーションの情報を入力して、[作成]ボタンを押してキーの発行を行います。

      この情報を使ってAPI呼び出しを行います。
      こちらは「例」です。

       

    2. 登録が完了すると、Microsoft Translator は[マイ データ]に分類されます。

       

  3. Azure Media Indexerによるテキストメタデータの抽出

現在Azure Media Indexerを使うにはAPIを使用する必要があります。
ここでは、C#の例を見ていきましょう。

事前準備:

Azure Media Indexer設定ファイルの例です。

[indexing.config]

—————————————————————————————-

<!–?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration version=”2.0″>

<input>

<!– [Optional] [Recommended] Metadata of the input media file(s) –>

<metadata key=”title” value=”TechEd 2014 Key Note” />

<metadata key=”description” value=”So much FAN video.” />

</input>

<settings>

<!– Reserved –>

</settings>

</configuration>

—————————————————————————————-

 

Task Preset for Azure Media Indexer:
http://msdn.microsoft.com/en-us/library/dn783454.aspx

 

  1. プログラム作成

通常のVoDのエンコード処理と変わりません。

Visual Studio で、C#の[コンソール アプリケーション]のプロジェクトを作成します。
その後、NuGetパッケージにて、[Windows Azure Media Services .NET SDK Extensions] をインストールしてください。

 

Visual Studio のプロジェクト内は以下の通りです。

主要ファイルになります。

  • BingTranslatorSvc.cs:    Microsoft Translatorとやり取りするクラスです。
  • Indexing.config:        Azure Media Indexer の設定ファイルです (上述)。
  • Program.cs:        メイン処理です。

 

メインとなる、Program.csの中から順にみていきましょう。

名前空間

———————————————————————
using System;

using System.Configuration;

using System.Collections.Generic;

using System.Linq;

using System.IO;

using System.Net;

using System.Text;

using System.Threading.Tasks;

using System.Diagnostics;

using System.Xml;

using System.Xml.Linq;

 

using Microsoft.WindowsAzure.MediaServices.Client;
———————————————————————

System.Configurationが初期設定では参照されていませんので、[参照設定] を右クリックして出てくるポップアップメニューから[参照の追加]を押して、”System.Configuration” を追加してください。

 

 

クラス変数

app.config内からから取得しているものばかりです。

————————————–
private static string TranslatorClientID = ConfigurationManager.AppSettings[“TranslatorClientID”];

private static string TranslatorClientSecret = ConfigurationManager.AppSettings[“TranslatorClientSecret”];

private static string uploadFile = ConfigurationManager.AppSettings[“uploadfile”];

————————————–

 

[app.config] の一部

—————————————-
<!–?xml version=”1.0″ encoding=”utf-8″?>

<configuration>

<appSettings>

TranslatorClientID” value=”” />

TranslatorClientSecret” value=”” />

accountName” value=”” />

accountKey” value=”” />

uploadfile” value=”C:\Users\dahatake\Desktop\KEY002.mp4″ />

</appSettings>

————————————–

 

Azure Media Services 接続

————————————–
var context = new CloudMediaContext(

ConfigurationManager.AppSettings[“accountName”],

ConfigurationManager.AppSettings[“accountKey”]

);

—————————————

Azure Media Servicesへの接続情報は、Azure管理画面より取得ください。

 

ファイルのアップロード
—————————————————-
var asset = context.Assets.CreateFromFile(

uploadFile,

AssetCreationOptions.None,

(a, p) =>

{

Console.WriteLine(” 経過 {0}%”, p.Progress);

});

—————————————————-
これは説明不要かと。

 

ジョブ実行

ここでIndexingのジョブを実行します。といっても、Media Processorとして”Azure Media Indexer”の指定をして、先ほどの設定ファイルの内容を文字列として渡すだけです。

—————————————————–
// 1. ジョブ作成

var configuration = File.ReadAllText(“indexing.config”);

 

var job = context.Jobs.CreateWithSingleTask(

“Azure Media Indexer”,

configuration,

asset,

asset.Name + “-Indexed”,

AssetCreationOptions.None);

 

// 2. ジョブ実行.

job.Submit();

job = job.StartExecutionProgressTask(

j =>

{

Console.WriteLine(” 状態: {0}”, j.State);

Console.WriteLine(” 経過: {0:0.##}%”, j.GetOverallProgress());

},

System.Threading.CancellationToken.None).Result;

var outputAsset = job.OutputMediaAssets.FirstOrDefault();

————————————————————————-

 

動画配信ポイント作成

元ファイルがmp4ファイルの場合は、そのままHTML5ビデオにプログレッシブダウンロード方式にて配信ができます。ここでは、アップロードしたファイルをそのまま配信に使います。

————————————————————————–

context.Locators.CreateLocator(

LocatorType.Sas,

asset,

context.AccessPolicies.Create(

“Streaming Access Policy”,

TimeSpan.FromDays(7), //7日間のみ公開

AccessPermissions.Read)

);

————————————————————————–

 

ファイルのダウンロード

サンプルという事もあり、作成されたファイルを全てダウンロードして、デスクトップに保存します。
毎回これが必要というわけではありません。

 

————————————————————————–
var TTMLFile = “”;

foreach (IAssetFile file in outputAsset.AssetFiles)

{

Console.WriteLine(” ファイルダウンロード中: {0}”, file.Name);

file.Download(Environment.GetEnvironmentVariable(“USERPROFILE”) +

@”\Desktop\” +

file.Name);

 

// ttml は翻訳対象

if (file.Name.EndsWith(“.ttml”))

{

TTMLFile = Environment.GetEnvironmentVariable(“USERPROFILE”)

+ @”\Desktop\”

+ file.Name;

}

}

————————————————————————–

 

ここで、実際にAzure Media Indexerによって作成されたttmlファイルの内容をみましょう。

[KEY002.mp4.ttml] の一部

————————————————————————-
<!–?xml version=”1.0″ encoding=”utf-8″?>

xml:lang=”en-us” xmlns=”http://www.w3.org/ns/ttml&#8221; xmlns:tts=”http://www.w3.org/ns/ttml#styling&#8221; xmlns:ttm=”http://www.w3.org/ns/ttml#metadata”&gt;

<head>

<metadata>

<ttm:title>Media.wvx.aib

<ttm:copyright>Copyright (c) 2013 Microsoft Corporation. All rights reserved.

</metadata>

<styling>

 

</styling>

<layout>

xml:id=”CaptionArea” tts:origin=”0c 12.6c” tts:extent=”32c 2.4c” tts:backgroundColor=”rgba(0,0,0,160)” tts:displayAlign=”center” tts:padding=”0.3c 0.5c” />

</layout>

</head>

<body region=”CaptionArea”>

…welcome executive vice …zygote guthrie

Good morning everyone and welcome …to …

We live in a mobile first cloud first-world yesterday we

————————————————————————-

  •  タグに、抽出結果の文字列が入っています。
  • それぞれ”begin“と”end“があります。再生開始してからのその文字が話されていた時間、という意味です。

Microsoft Translatorの呼び出し

さて、この先で作成されたTTMLの英文を翻訳するわけですが、その為にMicrosoft Translatorを呼び出す処理を書いていきます。

[BingTranslatorSvc.cs]

ここでは全文を載せます。ちょっと長いですが…

-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using System.Web;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Threading;
namespace AzureMediaIndexer
{
    // http://blogs.msdn.com/b/translation/p/gettingstarted1.aspx
    class BingTranalatorSvc
    {
        public string from    = "en";
        public string to    = "ja";
        // Azure MarketPlace と紐づけ
				
        //Get Client Id and Client Secret from https://datamarket.azure.com/developer/applications/
        public string clientID        = "";
        public string clientSecret    = "";
        
        public string Translate(string text)
        {
            string result = "";
            // BingTranslator アクセス用のアクセストークンをAzure DataMarketから取得
				
            var accessToken = new AdmAuthentication(clientID, clientSecret);
            
            string uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + System.Web.HttpUtility.UrlEncode(text) + "&from=" + from + "&to=" + to;
            string authToken = "Bearer " + accessToken.GetAccessToken().access_token;
            // Microsoft Translator呼び出し
				
            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
            httpWebRequest.Headers.Add("Authorization", authToken);
            // 結果取得
				
            WebResponse response = null;
            response = httpWebRequest.GetResponse();
            using (Stream stream = response.GetResponseStream())
            {
                System.Runtime.Serialization.DataContractSerializer dcs = new System.Runtime.Serialization.DataContractSerializer(Type.GetType("System.String"));
                result = (string)dcs.ReadObject(stream);
            }
            return result;
        }
        // Refer obtaining AccessToken (http://msdn.microsoft.com/en-us/library/hh454950.aspx) 
        [DataContract]
        public class AdmAccessToken
        {
            [DataMember]
            public string access_token { get; set; }
            [DataMember]
            public string token_type { get; set; }
            [DataMember]
            public string expires_in { get; set; }
            [DataMember]
            public string scope { get; set; }
        }
        public class AdmAuthentication
        {
            public static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
            private string clientId;
            private string clientSecret;
            private string request;
            private AdmAccessToken token;
            private Timer accessTokenRenewer;
            //Access token expires every 10 minutes. Renew it every 9 minutes only.
            private const int RefreshTokenDuration = 9;
            public AdmAuthentication(string clientId, string clientSecret)
            {
                this.clientId = clientId;
                this.clientSecret = clientSecret;
                //If clientid or client secret has special characters, encode before sending request
                this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
                this.token = HttpPost(DatamarketAccessUri, this.request);
                //renew the token every specfied minutes
                accessTokenRenewer = new Timer(new TimerCallback(OnTokenExpiredCallback), this, TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
            }
            public AdmAccessToken GetAccessToken()
            {
                return this.token;
            }
            private void RenewAccessToken()
            {
                AdmAccessToken newAccessToken = HttpPost(DatamarketAccessUri, this.request);
                //swap the new token with old one
                //Note: the swap is thread unsafe
                this.token = newAccessToken;
            }
            private void OnTokenExpiredCallback(object stateInfo)
            {
                try
                {
                    RenewAccessToken();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(string.Format("Failed renewing access token. Details: {0}", ex.Message));
                }
                finally
                {
                    try
                    {
                        accessTokenRenewer.Change(TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(string.Format("Failed to reschedule the timer to renew access token. Details: {0}", ex.Message));
                    }
                }
            }
            private AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
            {
                //Prepare OAuth request 
                WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.Method = "POST";
                byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
                webRequest.ContentLength = bytes.Length;
                using (Stream outputStream = webRequest.GetRequestStream())
                {
                    outputStream.Write(bytes, 0, bytes.Length);
                }
                using (WebResponse webResponse = webRequest.GetResponse())
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                    //Get deserialized object from JSON stream
                    AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
                    return token;
                }
            }
            
        }
    }
}
					
-----------------------------------------------------------------------------

ポイントです。

  • アクセストークンを取得する必要があります。それを” AdmAuthentication” クラスの内部で行っています。
    • Obtaining an Access Token:
      http://msdn.microsoft.com/en-us/library/hh454950.aspx
    • アクセストークンは10分で期限が切れます。よって切れた場合のコールバック処理をしています。
    • アクセストークンはHTTP Headerの中で、以下の形で追記します。
      • Bearer xxxx

ttmlから英文を切り出して、Microsoft Translatorを呼び出す

せっかくですから一度に複数言語に翻訳してみます。ここでは、日本語とクリンゴン語ですね。

——————————————————————————-
// Translator Language Codes:

// http://msdn.microsoft.com/en-us/library/hh456380.aspx

var langs = new string[]{

“ja”,    //日本語

“tlh”};    //クリンゴン語

BingTranalatorSvc translator = new BingTranalatorSvc();

translator.clientID = TranslatorClientID;

translator.clientSecret = TranslatorClientSecret;

int i = 0;

——————————————————————————-

  • Microsoft Azure Marketplace で作成した、Client IDとClient Secretを設定します。

注: クリンゴン語は地球上には存在していません。Star Trekの中のとある種族の話している言語です。Microsoft Translatorは、クリンゴン語への機械翻訳をしてくれます!

Microsoft Translatorによる機械翻訳呼び出し

——————————————————————————-

foreach (var lang in langs)

{

var TTMLjp = XDocument.Load(TTMLFile);

XNamespace ttmlns = “http://www.w3.org/ns/ttml&#8221;; //LINQ to XMLでクエリするためには、xmlnsの指定は必須

var transTargets = from p in TTMLjp.Descendants(ttmlns + “p”)

select p;

translator.to = lang;

foreach (var item in transTargets)

{

try

{

Console.WriteLine(” 機械翻訳: {0}:{1}/{2}”,

lang,

i,

item.Value);

item.SetValue(translator.Translate(item.Value));

i++;

}

catch (WebException we)

{

ProcessWebException(we);

break;

}

}

TTMLjp.Save(TTMLFile.Replace(“.ttml”,

string.Format(“.{0}.ttml”,lang)));

Console.WriteLine(” 機械翻訳 完了”);

Console.WriteLine(” 機械翻訳数: {0}:{1}/{2}”,

lang,

i,

transTargets.Count());

}

————————————————————-

  • LINQ to XMLにて、ttmlからタグの内容のみを抽出しています。

    • ttmlには、以下の名前空間が設定されていますので、XNamespace オブジェクトを設定しています。
    • LINQ構文が大変わかりやすいのがご理解いただけると思います。
  • 翻訳結果を、同じオブジェクトにセットしていますが、これでメモリー内のデータが上書きされます。
    • item.SetValue(translator.Translate(item.Value));
  • WebExceptionを拾っていますが、これはお勧めします。Microsoft Translatorのエラー詳細は、HTTP Responseに含まれていますので、その内容を読み取る必要があります。
    • ProcessWebExpressionはこんな感じです。

      ————————————————————————-
      private static void ProcessWebException(WebException e)

      {

      Console.WriteLine(“>>> Error: {0}”, e.ToString());

      // Obtain detailed error information

      string strResponse = string.Empty;

      using (HttpWebResponse response = (HttpWebResponse)e.Response)

      {

      using (Stream responseStream = response.GetResponseStream())

      {

      using (StreamReader sr = new StreamReader(responseStream, System.Text.Encoding.ASCII))

      {

      strResponse = sr.ReadToEnd();

      }

      }

      }

      Console.WriteLine(“>>> Http status code={0}, error message={1}”, e.Status, strResponse);

      }

      —————————————————————————

これで完了です。

以下、メイン部分のソースコード全文です。

[Program.cs]

このサンプルでは、それぞれの処理の実行時間を計測しています。

————————————————————————————————-

using System;

using System.Configuration;

using System.Collections.Generic;

using System.Linq;

using System.IO;

using System.Net;

using System.Text;

using System.Threading.Tasks;

using System.Diagnostics;

using System.Xml;

using System.Xml.Linq;

using Microsoft.WindowsAzure.MediaServices.Client;

namespace AzureMediaIndexer

{

class Program

{

private static string TranslatorClientID = ConfigurationManager.AppSettings[“TranslatorClientID”];

private static string TranslatorClientSecret = ConfigurationManager.AppSettings[“TranslatorClientSecret”];

private static string uploadFile = ConfigurationManager.AppSettings[“uploadfile”];

static void Main(string[] args)

{

// 処理時間の計測

var totalSw = new Stopwatch();

var sw = new Stopwatch();

totalSw.Start();

var context = new CloudMediaContext(

ConfigurationManager.AppSettings[“accountName”],

ConfigurationManager.AppSettings[“accountKey”]

);

Console.WriteLine(“*** 1. ファイルアップロード ***”);

sw.Start();

var asset = context.Assets.CreateFromFile(

uploadFile,

AssetCreationOptions.None,

(a, p) =>

{

Console.WriteLine(” 経過 {0}%”, p.Progress);

});

sw.Stop();

Console.WriteLine(” アップロード処理完了”);

Console.WriteLine(” アップロード処理時間: {0}”, sw.Elapsed.ToString());

Console.WriteLine(“*** 2. Indexing 実行 ***”);

// 2.1. ジョブ作成

var configuration = File.ReadAllText(“indexing.config”);

var job = context.Jobs.CreateWithSingleTask(

“Azure Media Indexer”,

configuration,

asset,

asset.Name + “-Indexed”,

AssetCreationOptions.None);

sw.Reset();

sw.Start();

// 2.2. ジョブ実行.

job.Submit();

job = job.StartExecutionProgressTask(

j =>

{

Console.WriteLine(” 状態: {0}”, j.State);

Console.WriteLine(” 経過: {0:0.##}%”, j.GetOverallProgress());

},

System.Threading.CancellationToken.None).Result;

sw.Stop();

Console.WriteLine(” Indexing 完了”);

Console.WriteLine(” Indexing 時間: {0}”, sw.Elapsed.ToString());

var outputAsset = job.OutputMediaAssets.FirstOrDefault();

Console.WriteLine(“***** 3. 配信ポイント作成 *****”);

// Progressive Download

context.Locators.CreateLocator(

LocatorType.Sas,

asset,

context.AccessPolicies.Create(

“Streaming Access Policy”,

TimeSpan.FromDays(7),

AccessPermissions.Read)

);

WriteToFile(String.Format(“{0}_SASURL.txt”,

asset.Name),

asset.AssetFiles.FirstOrDefault().GetSasUri().ToString());

Console.WriteLine(“*** 4. ファイルダウンロード ***”);

sw.Reset();

sw.Start();

var TTMLFile = “”;

foreach (IAssetFile file in outputAsset.AssetFiles)

{

Console.WriteLine(” ファイルダウンロード中: {0}”, file.Name);

file.Download(Environment.GetEnvironmentVariable(“USERPROFILE”) +

@”\Desktop\” +

file.Name);

// ttml は翻訳対象

if (file.Name.EndsWith(“.ttml”))

{

TTMLFile = Environment.GetEnvironmentVariable(“USERPROFILE”)

+ @”\Desktop\”

+ file.Name;

}

}

Console.WriteLine(“*** 5. Bing Translator での ttml 機械翻訳 ***”);

sw.Reset();

sw.Start();

// Translator Language Codes:

// http://msdn.microsoft.com/en-us/library/hh456380.aspx

var langs = new string[]{

“ja”,    //日本語

“tlh”};    //クリンゴン語

BingTranalatorSvc translator = new BingTranalatorSvc();

translator.clientID = TranslatorClientID;

translator.clientSecret = TranslatorClientSecret;

int i = 0;

foreach (var lang in langs)

{

var TTMLjp = XDocument.Load(TTMLFile);

XNamespace ttmlns = “http://www.w3.org/ns/ttml&#8221;; //LINQ to XMLでクエリするためには、xmlnsの指定は必須

var transTargets = from p in TTMLjp.Descendants(ttmlns + “p”)

select p;

translator.to = lang;

foreach (var item in transTargets)

{

try

{

Console.WriteLine(” 機械翻訳: {0}:{1}/{2}”,

lang,

i,

item.Value);

item.SetValue(translator.Translate(item.Value));

i++;

}

catch (WebException we)

{

ProcessWebException(we);

break;

}

}

TTMLjp.Save(TTMLFile.Replace(“.ttml”,

string.Format(“.{0}.ttml”,lang)));

Console.WriteLine(” 機械翻訳 完了”);

Console.WriteLine(” 機械翻訳数: {0}:{1}/{2}”,

lang,

i,

transTargets.Count());

}

Console.WriteLine(” 機械翻訳時間: {0}”, sw.Elapsed.ToString());

Console.WriteLine();

Console.WriteLine(“全ての処理が終了しました。Indexing 結果がデスクトップに出力されていますので、ご確認ください。”);

Console.WriteLine(“総処理時間: {0}”, totalSw.Elapsed.ToString());

Console.WriteLine(“何かキーを押してください。”);

Console.ReadLine();

}

///

/// Utility: 文字列のファイル出力

///

/// outFileName”>

/// fileContent”>

static void WriteToFile(string outFileName, string fileContent)

{

System.IO.StreamWriter sr = System.IO.File.CreateText(

Environment.GetEnvironmentVariable(“USERPROFILE”) +

@”\Desktop\” +

outFileName);

sr.Write(fileContent);

sr.Flush();

sr.Close();

}

private static void ProcessWebException(WebException e)

{

Console.WriteLine(“>>> Error: {0}”, e.ToString());

// Obtain detailed error information

string strResponse = string.Empty;

using (HttpWebResponse response = (HttpWebResponse)e.Response)

{

using (Stream responseStream = response.GetResponseStream())

{

using (StreamReader sr = new StreamReader(responseStream, System.Text.Encoding.ASCII))

{

strResponse = sr.ReadToEnd();

}

}

}

Console.WriteLine(“>>> Http status code={0}, error message={1}”, e.Status, strResponse);

}

}

}

————————————————————————————————-

プログラム実行

早速Visual Studio から実行してみましょう。

結構時間がかかりますね。

実行結果の確認

デスクトップに幾つかファイルが出力されています。

このうち、”.ttml”を使用します。

  1. HTMLページ作成

以下の様になります。

[index.html]

———————————————————
<!––>DOCTYPE html>

Azure Media Indexer での字幕作成

Segoe UI’, Tahoma, Geneva, Verdana, sans-serif; font-size: x-large;”>

HTML5 Video + Track

字幕: Azure Media Indexer と Bing Translator で自動生成

ビデオプレイヤーの[CC]ボタンを押して、字幕の切り替えを試してください

</body>

</html>

————————————————————

  • Videoのsrcには、mp4ファイル向けに作成したSAS URLを指定しています。
  • trackタグは:
    • idは必須です
    • srcに.ttmlファイルを指定しています。ここでは、一緒にWeb Serverにアップロードして使います
    • label の部分がプレイヤーの字幕の表示文字列になります。
    • defaultと設定してあるものが、初期値で表示されます。

 

  1. Azure WebSiteの作成

Azure WebSiteを作成して、ファイルをアップロードしましょう。

Azureの管理画面で、[新規] – [Webサイト] – [簡易作成] から、以下を参考にURLとデータセンターの場所を選択します。

 

10秒程度で本番サイトが使えるようになります。

作成した、WebSiteを選択して、[構成] のタブに移動します。
少し下にスクロールすると[VISUAL STUDIO ONLINEでの編集]という項目があります。これを「オン」にして、画面したの[保存]ボタンを押してください。

 

設定が完了したら、[ダッシュボード]に戻ります。画面右側の[概要]の中に[Visual Studio Onlineでの編集]という項目が表示されます。これをクリックします。

 

ブラウザーの中でコーディングが出来る、Visual Studio Online “Monaco”という環境が立ち上がってきます。
ほんの少し修正するだけなのに、PC上でソースコードを直して、アップロードしなおす、という事をする必要がありません。直接Azure WebSite上にあるHTML, PHPなどのソースを編集して、保存できるのです。
それに加えて、ドラックアンドドロップでファイルをアップロードする機能まであります。

ドラックアンドドロップします。

 

ファイルがアップロードされているのが確認できます。
HTMLの場合は、タグとして認識されていますので、エディター上で色分けがされて大変読みやすくなっています。

手元でファイル作成して、アップロード。という方法をとりましたが、いきなり”Monaco”に入って、”Monaco”の中でコーディングする、という方法でも構いません。

 

  1. MIMEの設定

Azure WebSiteでは、ttmlのMIME設定がされていませんので、そのままでは動作しません。
“text/xml”のmime設定を行います。
Azure WebSiteの実体はIISですので、IISのweb.configファイルを作成し、MIME設定を行います。

 

[web.config]

—————————————————————————————————-
<?xml version=”1.0″ encoding=”utf-8″?>

<!– For HTML5 configuration details and recommendations, see https://github.com/h5bp/server-configs/wiki/web.config –>

<configuration>

<system.webServer>

<staticContent>

<remove fileExtension=”.ttml” />

<mimeMap fileExtension=”.ttml” mimeType=”text/xml” />

</staticContent>

</system.webServer>

</configuration>

 

Azure WebSiteは最終的にこのようになりました。

 

画面左側の再生ボタンを押して、本番サイトをみてみます。

 

実行結果はこのような感じです。

 

クリンゴン語で表示されていますね。

 

[CC] のところで設定した字幕が選べるようになっています。

 

  1. まとめ

Azure Media Indexerを使うと、そのままHTML5 Videoで作成できるTTMLのファイルが作成できる事を見てきました。
そして、Microsoft Translatorで、かなり意味の分かる各国語に機械翻訳できるところも見てきました。

話している場所は、シーンになります。検索結果、ビデオファイルのURLがわかるのではなく、ビデオの中のどのシーンに飛ばせばいいのかまでわかります。

Azure Media Indexerはその他にも面白いファイルを作成してくれます。

是非、いろんな可能性にチャレンジしてください!

 

ご参考:

Azure Media Indexer料金:

http://azure.microsoft.com/ja-jp/pricing/details/media-services/#encoding

 

Introducing Azure Media Indexer:
http://azure.microsoft.com/blog/2014/09/10/introducing-azure-media-indexer/

MSDN: Indexing Media Files with Azure Media Indexer:
http://msdn.microsoft.com/en-us/library/dn783455.aspx

What Can You Do with Azure Media Indexer? [William Zhang BLOG]:
http://blogs.msdn.com/b/playready4/archive/2014/09/17/what-can-you-do-with-azure-media-indexer.aspx

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中