AzureMediaServices

This is an article on how you can achieve Azure Media Services (AMS) streaming traffic distribution with Traffic Manager.

The process for a client to find target AMS streaming endpoints

The figure shows how a client find target AMS streaming endpoints with Traffic Manager and requests from video players are distributed to streaming endpoints in AMS:

Controling Azure Media Services Traffic with Traffic Manager

When AMS endpoints are added to an Azure Traffic Manager profile, Azure Traffic Manager keeps track of the status of the endpoints (running, stopped, or deleted) so that it can decide which of those endpoints should receive traffic. You can configure the way to route network traffic to the endpoints by choosing traffic routing methods available in Traffic Manager.

Configuration procedure

Suppose that you have 2 AMS accounts (amsaccount1, amsaccount2), and that you want to distribute requests to your Traffic Manager domain (myamsstreaming.trafficmanager.net) from video player clients to streaming endpoints in AMS. When AMS endpoints are added to an Azure Traffic Manager profile (myamsstreaming), Azure Traffic Manager keeps track of the status of your AMS streaming endpoints (running, stopped, or deleted) so that it can decide which of those endpoints should receive traffic. However, when it comes to AMS endpoints, it has to be toward a custom domain, NOT simply a Traffic Manager domain for clients’ traffic to be distributed into AMS endpoints using Traffic Manager. So let’s suppose you prepare a custom domain: streaming.mydomain.com.

Example accounts and domains

(1) Point a custom domain to a Traffic Manager domain

You add the following alias (CNAME) to point the custom domain to the traffic manager domain:

streaming.mydomain.com IN CNAME myamsstreaming.trafficmanager.net

Useful Link for this step: Point a company Internet domain to an Azure Traffic Manager domain

(2) Add Azure Media Services origin hosts to the Traffic Manager

Add AMS endpoints to an Azure Traffic Manager profile as “External Endpoint” via either Azure Portal or Azure CLI / PowerShell. Here is an image of adding endpoints in Azure portal:

Add endpoints to Traffic Manager

Useful Link for this step: Add, disable, enable, or delete endpoints

(3) Custom domain name ownership verification

First of all, get Media Service Account IDs (GUID) for your AMS accounts in this step. To find the Azure Media Service ID , go to the Azure portal and select your Media Service account. The Azure Media Service ID appears on the right of the DASHBOARD page. Let’s suppose you get the following account IDs for AMS accounts (amsaccount1, amsaccount2):

Then, create CNAME that maps (accountId).(parent custom domain) to verifydns.(mediaservices-dns-zone). This is necessary to proves that the Azure Media Services ID has the ownership of the custom domain. Here are CNAMEs to create in this step:

## <MediaServicesAccountID>.<custom parent domain> IN CNAME verifydns.<mediaservices-dns-zone>

## Custom name Ownership verification for amsaccount1
8dcbe520-59c7-4591-8d98-1e765b7f3729.mydomain.com IN CNAME  verifydns.mediaservices.windows.net

## Custom name Ownership verification for amsaccount2
5e0e6784-4ed0-40a0-8444-33da6d4f7171.mydomain.com IN CNAME  verifydns.mediaservices.windows.net

Refer to CustomHostNames section of StreamingEndpoint document to learn more about the configuration in this step.

(4) Add Custom host name to each Azure Media Service streaming endpoint

Once you completed “Custom domain name ownership verification” configuration, you then need to configure to add custom host name to each Azure Media Service streaming endpoint. Unfortunately new portal doesn’t include capability to add custom domain to the streaming endpoint. You can set it either using REST API directly or using Azure Media Explorer. Here is how you add custom host name to the streaming endpoint in Azure Media Explorer:

azure-media-explorer-custom-host-streaming-endpoint

Choose “Streaming endpoint” in the top menu, right click on your streaming endpoint, and select “Streaming endpoint information and settings”. In Streaming endpoint information form, type in your custom host name for the endpoint, and click “Update settings and close”. That’s it.

(5) Test video playback with your custom domain

Once all configurations above are completed (+ DNS settings are reflected), you will see the custom domain name lookup points to either of AMS endpoints added to the traffic manager like this:

$ dig streaming.mydomain.com

;; ANSWER SECTION:
streaming.mydomain.com. 600 IN CNAME myamsstreaming.trafficmanager.net.
myamsstreaming.trafficmanager.net. 300 IN CNAME amsaccount1.streaming.mediaservices.windows.net.
amsaccount1.streaming.mediaservices.windows.net. 60 IN CNAME wamsorigin-origin-903f1f37105244fba2270ae7b64021bd.cloudapp.net.
wamsorigin-origin-903f1f37105244fba2270ae7b64021bd.cloudapp.net. 60 IN A 104.215.4.76

Make sure to check if the custom name lookup points to the other endpoint when one of the endpoints are down.

Finally, check if you can playback video with your custom domain.

$ curl http://amsaccount1.streaming.mediaservices.windows.net/ee2e5286-d3fa-40fc-a393-c3c2a3ca5a84/BigBuckBunny.ism/manifest
<?xml version="1.0" encoding="UTF-8"?><SmoothStreamingMedia MajorVersion="2" MinorVersion="2" Duration="84693333" TimeScale="10000000"><StreamIndex Chunks="2" Type="audio" Url="QualityLevels({bitrate})/Fragments(aac_eng_2_128={start time})" QualityLevels="1" Language="eng" Name="aac_eng_2_128"><QualityLevel AudioTag="255" Index="0" BitsPerSample="16" Bitrate="128000" FourCC="AACL" CodecPrivateData="1190" Channels="2" PacketSize="4" SamplingRate="48000" /><c t="0" d="60160000" /><c d="24533333" /></StreamIndex><StreamIndex Chunks="2" Type="video" Url="QualityLevels({bitrate})/Fragments(video={start time})" QualityLevels="5"><QualityLevel Index="0" Bitrate="2896000" FourCC="H264" MaxWidth="1280" MaxHeight="720" CodecPrivateData="000000016764001FACD9405005BB011000000300100000030300F18319600000000168EBECB22C" /><QualityLevel Index="1" Bitrate="1789000" FourCC="H264" MaxWidth="960" MaxHeight="540" CodecPrivateData="000000016764001FACD940F0117EF011000003000100000300300F1831960000000168EBECB22C" /><QualityLevel Index="2" Bitrate="946000" FourCC="H264" MaxWidth="640" MaxHeight="360" CodecPrivateData="000000016764001EACD940A02FF97011000003000100000300300F162D960000000168EBECB22C" /><QualityLevel Index="3" Bitrate="612000" FourCC="H264" MaxWidth="480" MaxHeight="270" CodecPrivateData="0000000167640015ACD941E08FEB011000000300100000030300F162D9600000000168EBECB22C" /><QualityLevel Index="4" Bitrate="324000" FourCC="H264" MaxWidth="320" MaxHeight="180" CodecPrivateData="000000016764000DACD941419F9F011000000300100000030300F14299600000000168EBECB22C" /><c t="0" d="60000000" /><c d="24583333" /></StreamIndex></SmoothStreamingMedia>

$ curl http://streaming.mydomain.com/ee2e5286-d3fa-40fc-a393-c3c2a3ca5a84/BigBuckBunny.ism/manifest
<?xml version="1.0" encoding="UTF-8"?><SmoothStreamingMedia MajorVersion="2" MinorVersion="2" Duration="84693333" TimeScale="10000000"><StreamIndex Chunks="2" Type="audio" Url="QualityLevels({bitrate})/Fragments(aac_eng_2_128={start time})" QualityLevels="1" Language="eng" Name="aac_eng_2_128"><QualityLevel AudioTag="255" Index="0" BitsPerSample="16" Bitrate="128000" FourCC="AACL" CodecPrivateData="1190" Channels="2" PacketSize="4" SamplingRate="48000" /><c t="0" d="60160000" /><c d="24533333" /></StreamIndex><StreamIndex Chunks="2" Type="video" Url="QualityLevels({bitrate})/Fragments(video={start time})" QualityLevels="5"><QualityLevel Index="0" Bitrate="2896000" FourCC="H264" MaxWidth="1280" MaxHeight="720" CodecPrivateData="000000016764001FACD9405005BB011000000300100000030300F18319600000000168EBECB22C" /><QualityLevel Index="1" Bitrate="1789000" FourCC="H264" MaxWidth="960" MaxHeight="540" CodecPrivateData="000000016764001FACD940F0117EF011000003000100000300300F1831960000000168EBECB22C" /><QualityLevel Index="2" Bitrate="946000" FourCC="H264" MaxWidth="640" MaxHeight="360" CodecPrivateData="000000016764001EACD940A02FF97011000003000100000300300F162D960000000168EBECB22C" /><QualityLevel Index="3" Bitrate="612000" FourCC="H264" MaxWidth="480" MaxHeight="270" CodecPrivateData="0000000167640015ACD941E08FEB011000000300100000030300F162D9600000000168EBECB22C" /><QualityLevel Index="4" Bitrate="324000" FourCC="H264" MaxWidth="320" MaxHeight="180" CodecPrivateData="000000016764000DACD941419F9F011000000300100000030300F14299600000000168EBECB22C" /><c t="0" d="60000000" /><c d="24583333" /></StreamIndex></SmoothStreamingMedia>

Useful Links

過去に本ブログでビデオコンテンツを切り口とした音声認識OCR技術を利用したデモを紹介したが、ここではビデオコンテンツの中の人物出現箇所に連動して人物名を字幕で表示させるデモとその実装方法を紹介したい。人物識別にはAzureのCognitive ServicesのFace APIを使っていて、これで動画の中に出現する顔の検出を行い、予め登録している人物リストとのマッチングにより実現している。
Cognitive Serivcesとは視覚、音声、言語、知識などマイクロソフトがこれまで研究を通じて開発してきたさまざまな要素技術をAPIとして提供しているサービスのことで、最近巷で人工知能(AI)だとかインテリジェンスとかいうキーワードをよく耳にするのではないかと思うがAzure利用シナリオでそういったインテリジェンス(知能/知性)を兼ね備えたアプリを作る場合は間違いなく中核となるサービスの1つである。Face APIはその中でも顔の検出・識別や、顔にまつわる感情、特徴などメタデータ抽出に特化したAPIである。



Video Summarization and Face Detection Demo Screenshot

( デモサイト | Source Code )

主要テクノロジーと機能

下図は今回のデモ作成のために行っている処理フローと主要テクノロジーを表している。やっていることは大きく分けて3つ: (1) 動画コンテンツをAzure Media Encoder Standardを使ってフレームごとの静止画像の作成, (2) Cognitive ServicesのFace APIを使って1より得られた静止画像から顔の検出を行い予め登録している人物リストとマッチング(最も類似度が高いものを本人とみなす)して人物を識別, (3) 2で得られた各フレーム中の人物情報を時間順に並べて字幕(Closed Caption)用のデータファイルを生成。以下、各処理の詳細について説明する。


VideoFramesFaceFecognition_case1

1. Azure Media Encoder Standardでフレームごとの静止画生成

残念ながらFace APIはビデオコンテンツから直接顔検出することができないため、一旦ビデオコンテンツから各フレームごとの静止画を生成してその静止画を対象に処理を行う必要がある。ここでは各フレームごとの静止画生成にAzure Media Encoder Standard(MES)を利用する。MESを使うことでエンコードタスクとしてビデオコンテンツに対して様々な処理を行うことができるのだが、MESにはそのエンコードタスクの1つとしてサムネイル生成のためのタスクが用意されており、今回はこのサムネール生成タスクを利用する。他のエンコードタスク同様にサムネイル生成タスクについてもプリセットと呼ばれるエンコードに必要な情報を記述した XML または JSON形式ファイルを用意する必要がある。今回は1秒フレームごとにJPEG形式の静止画(サムネイル)を生成するために次のようなプリセット(amsmp-thumbnail-config.json)を用意した。

{
  "Version": 1.0,
  "Codecs": [
    {
      "Start": "00:00:00",
      "Step": "00:00:01",
      "Type": "JpgImage",
      "JpgLayers": [
        {
          "Quality": 90,
          "Type": "JpgLayer",
          "Width": 640,
          "Height": 360
        }
      ]
    }
  ],
  "Outputs": [
    {
      "FileName": "{Basename}_{Index}{Extension}",
      "Format": {
        "Type": "JpgFormat"
      }
    }
  ]
}

MESによるサムネイル処理実行方法やプリセットの詳細については「Media Encoder Standard を使用した高度なエンコード」や同ページの「サムネイルを生成する」項を参照ください。尚、今回のサムネイル生成のためのエンコーディング処理は小生自作の「azure-media-processor-java」を利用してバッチ実行している。

2. Cognitive Services Face APIによる顔の検出と人物の識別

ここではCognitive ServicesのFace APIを使って1で得られたフレームごとの静止画像に対して顔検出を行い、予め登録している人物リスト(Face APIでいうところのPerson Group)と比較して最も類似度の高い人物(Face APIでいうところのPerson )をその本人として識別する。

2-1. 人物リスト(Person Group)の作成

人物リスト(Person Group)の作成で必要な作業とFace APIの利用インターフェースは次の通り:

2-2. 静止画像中の顔認識と人物識別

ここで行う処理の流れとFace APIの利用インターフェースは次の通り:

3. 字幕(Closed Caption)データファイルの生成

2で得られた各フレーム中の人物情報と各フレームの時間を元に字幕用のデータフォーマットであるWebVTTフォーマットファイルを生成する。以下、6秒~30秒までの字幕出力を期したWebVTTファイルのサンプルであるが、見ていただいてわかる通りフレームの時間(最小秒単位)とそこで得られた人物名をセットで記述するとても単純なフォーマットとなっている。

00:00:06.000 --> 00:00:07.000
Satya Nadella(0.73295)

00:00:07.000 --> 00:00:08.000
Satya Nadella(0.6313)

00:00:27.000 --> 00:00:28.000
Bryan Roper(0.68094)

00:00:29.000 --> 00:00:30.000
Bryan Roper(0.54939)

各フレームの時間について、今回のビデオコンテンツのフレームは1秒ごとに取得しており、フレームごとの静止画像ファイルにはフレームの順番がPostfixとしてファイル名に含まれているため単純にファイル名からフレームの時間が特定できるようになっている(例, 10番目のファイル= videoassetname_000010.jpg)。もし今回のような機械的なルールがない場合はフレーム用画像ファイル名と時間のマッピングが必要となる。

ビデオコンテンツと字幕の再生は「ビデオコンテンツの音声認識デモ」でも紹介したようにHTML5のtrackタグエレメントによるビデオファイルの字幕表示機能使って人物名の字幕表示を実現している。本デモではHTML5に下記のようにビデオファイル(MP4)をVideoソースとしてtrackエレメントにWebVTTファイル(build2016keynote.vtt)を指定している。

<video id="Video1" controls autoplay width="600">
    <source src="KEY01_VideoThumbnail.mp4" srclang="en" type="video/mp4">
    <track id="trackJA"  src="build2016keynote.vtt"  kind="captions" srclang="ja" label="Person Name" default>
</video>

デモデータ作成手順

GithubプロジェクトページVideoFramesFaceRecognition-Pythonの1. Preparationと2. Batch executionを実施いただければFace APIで識別した各フレームごとの人物名を元に字幕データ*.vttファイルが生成されデモページ表示のための準備は完了する。最後に表示用の静的ページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlの変更のみでいけるはず。

本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。

Azure Media Analytics Face Detectorを活用した処理の効率化

今回の人物識別ではビデオコンテンツの全てのフレームに対してFace APIを使って顔検出処理を行っているが、これでは顔出現フレームが少ないコンテンツの場合には無駄なFace APIリクエストが大量に発生してしまうため効率的な処理とは言えない。ということで、ここではAzure Media Face Detectorを活用して処理を効率化する方法を紹介したい。
Azure Media Face DetectorはAzure Media Servicesのメディアプロセッサ(MP)の1つで、ビデオコンテンツから顔の検出や感情の検出をすることができる。残念ながらAzure Media Face DetectorはFace APIのように顔の識別を行うことはできないものの、ビデオコンテンツから直接顔を検出することができる、即ちビデオコンテンツから直接顔が存在するフレームを特定することができる。よって、この機能を利用して一旦Azure Media Face Detectorで顔が検出されたフレームのみに絞り込んでからFace APIを使ってフレームの静止画像に対して顔検出・顔識別を行うことで無駄なFace APIリクエストを減らして処理の効率化を図ることができる。処理フローとしては次のようなイメージ。


VideoFramesFaceFecognition_case2

おまけ: Video Summarization

デモページをみていただくとお分かりのように今回のデモでは3分のビデオコンテンツを題材としているが、元ネタはChannel9で公開されている計138分のBuild 2016のキーノートセッションである。このキーノートのセッションはデモコンテンツとしてはあまりに長かったのでこれをAzure Media Video Thumbnailsメディアプロセッサ(MP)を使って3分に要約している。Azure Media Video Thumbnailsはアルゴリズムベースで特徴シーンの検出とそれらを結合(サブクリップ)してビデオコンテンツを指定した長さに要約することができるMPで、現在Public Previewリリース中(2016年12月現在)。

参考までに、要約(3分:180秒)に使用したAzure Media Video Thumbnailsのタスクプリセットは以下の通り:

{
    "version": "1.0",
    "options": {
        "outputAudio": "true",
        "maxMotionThumbnailDurationInSecs": "180",
        "fadeInFadeOut": "true"
    }
}

END

OCRとはOptical Character Recognitionの略で日本語にすると光学文字認識と訳されており、ざっくりと画像の中の文字をテキストに変換する技術のことを指す。テキストに変換されるということは勘が鋭い皆さんはお気づきだと思うが、テキストの全文検索であったり、テキストから音声への変換、さらには機械翻訳を使って多言語への変換といった展開が考えられる。そんな可能性を秘めたOCRであるが、ここではそのOCRの技術を使ってビデオファイルから抽出したテキストデータを元にビデオに字幕表示したり、動画中に表示される文字を全文検索をするデモを紹介したい。内容的には「Azure Media & Cognitiveデモ:Speech-To-Text」で紹介したデモのOCR版といったところ。



Video OCR Demo Screenshot

( デモサイト | Source Code )

主要テクノロジーと機能

Azure Media OCRメディアプロセッサによるテキスト抽出

このデモではAzure Media OCRメディアプロセッサー(MP)を使用してビデオファイル内のテキストコンテンツを検出してテキストファイルを生成している。OCRメディアプロセッサーは入力パラメータによりビデオ解析の挙動を調整することができる。主なパラメータとしては検索対象テキストの言語(日本語もサポート)、テキストの向き、サンプリングレート、ビデオフレーム内のテキスト検出対象のリージョンがあるが、本デモでの入力パラメータ(Video-OCR-Search-Python/src/ocr-detectregion.json)は以下の通り検索対象言語は日本語、1秒おきのサンプリングレート、テキスト検出対象のリージョンからビデオフレーム内の上部1/4を省く設定(検出対象をフレームトップから85 pixel以下を対象)にしている。

{
    "Version":"1.0",
    "Options":
    {
        "Language":"Japanese",
        "TimeInterval":"00:00:01.000",
        "DetectRegions":
        [
            {"Left":"0","Top":"85","Width":"1280","Height":"635"}
        ]
    }
}

そして、Azure Media OCRメディアプロセッサはビデオで検出された文字を下記のような表示時間に基づいてセグメント化された形で結果出力する。結果ファイルの完全版はこちら(azuresubs.json)を参照ください。

{
    "fragments": [
        {
            "start": 0
            "interval": 319319,
            "duration": 319319,
            "events": [
                [
                    {
                        "language": "Japanese",
                        "text": "Azure の 契 約 内 容 を 変 更 す る Microsoft Azure"
                    }
                ]
            ]
        },
        {  /* fragment1 */ },
        {  /* fragment2 */ },
        ...
        {  /* fragmentN */ }
    ],
    "version": 1,
    "framerate": 29.97,
    "height": 720,
    "width": 1280,
    "offset": 0,
    "timescale": 30000
}

入力パラメータと出力形式共に詳細はこちらのドキュメントを参照いただくとしてAzure Media OCRメディアプロセッサ利用の注意点として次の2つがある:

字幕(Closed Caption)データフォーマットへの変換

まず上記Azure Media OCRメディアプロセッサー(MP)から出力されたJSONファイルの内容を元に字幕用のデータフォーマットであるWebVTTフォーマットファイルを生成している。そして「Azure Media & Cognitiveデモ:Speech-To-Text」でも紹介したようにHTML5のtrackタグエレメントによるビデオファイルの字幕表示機能使ってOCRの内容の字幕表示を実現している。本デモではHTML5に下記のように動画(TransferanAzuresubscriptionJP.mp4)をVideoソースとしてtrackエレメントにWebVTTファイル(azuresubs.vtt)を指定している。

<video id="Video1" controls autoplay width="600">
    <source src="TransferanAzuresubscriptionJP.mp4" srclang="en" type="video/mp4">
    <track id="trackJA"  src="azuresubs.vtt"  kind="captions" srclang="ja" label="OCR Subtitle" default>
</video>

Azure Searchによる全文検索

デモページ上部にある検索窓にキーワードを入力してGoボタンを押すとビデオコンテンツからOCR抽出されたテキストを元に生成された字幕データを全文検索してキーワードにマッチしたテキストとその表示時間に絞り込むことができる。仕組みは「Azure Media & Cognitiveデモ:Speech-To-Text」と全く同じで、Azure Searchを使用して字幕データを解析して字幕表示時間とその対応テキストを1ドキュメントレコードとしてAzure Searchにインジェストしてその生成されたインデックスに対してキーワードを元に全文検索することで実現している。検索用のインデックススキーマもまったくおなじで次のように字幕表示時間とその対応テキストをレコード単位となるように定義している。

{
    "name": "ocr",
    "fields": [
        { "name":"id", "type":"Edm.String", "key": true, "searchable": false, "filterable":false, "facetable":false },
        { "name":"contentid", "type":"Edm.String","searchable": false, "filterable":true, "facetable":false },
        { "name":"beginsec", "type":"Edm.Int32", "searchable": false, "filterable":false, "sortable":true, "facetable":false },
        { "name":"begin", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"end", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"caption", "type":"Edm.String", "searchable": true, "filterable":false, "sortable":false, "facetable":false, "analyzer":"ja.microsoft" }
     ]
}

デモデータ作成手順

GithubプロジェクトページVideo-OCR-Search-Pythonの1. Preparationと2. Batch executionを実施いただければOCR抽出されたテキストを元に字幕データ*.vttファイルが生成され、そのテキストがAzure Searchに格納されてデモページ表示のための準備は完了する。最後に表示用のページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlとsearch.jsの変更のみでいけるはず。

本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。

Enjoy Video OCR demo!

ビデオコンテンツを音声認識エンジンでテキスト化してそれを元にスピーチ検索するデモコンテンツを紹介したい。これは過去にde:code2016というマイクロソフトの開発者向けイベントで行ったブレイクアウトセッション「DEV-18: Azure Search Deep Dive」にて紹介したビデオコンテンツのスピーチ検索デモを簡略化して再利用しやすいものにしたものである。



Video STT Demo Screenshot

( デモサイト | Source Code )

主要テクノロジーと機能

Azure Media Indexer 2 Previewによる音声からテキスト抽出

このデモではAzure Media Indexer 2 Preview メディア プロセッサー (MP)を使用してビデオコンテンツからテキストを抽出している。このAzure Media Indexer 2 Previewは自然言語処理(NLP)や音声認識エンジンを駆使してビデオコンテンツより字幕用データ(時間やテキスト)や検索可能にするためのメタデータを抽出することができる。Indexer 2という名前の通り前のバージョンであるAzure Media Indexerが存在するが、これと比較すると、Azure Media Indexer 2 Previewは、インデックス作成が高速化され、より多くの言語をサポートしていることが特徴である。2016年11月6日時点で英語、スペイン語、フランス語、ドイツ語、イタリア語、中国語、ポルトガル語、アラビア語などがサポートされている(残念ながら日本語はまだ未サポート)。

下イメージはAzure Media Indexer 2 (Preview)で生成されるTTMLWebVTTという代表的な字幕データフォーマット。


AzureMediaIndexer-ClosedCaption

HTML5と字幕(Closed Caption)

HTML5にはtrackタグエレメントを使ってビデオファイルに字幕を表示する機能が標準的に実装されている。本デモではHTML5に下記のように動画(Python_and_node.js_on_Visual_Studio.mp4)をVideoソースとしてtrackエレメントに字幕WebVttファイル(build2016breakout.vtt)を指定している。

<video id="Video1" controls autoplay width="600">
    <source src="Python_and_node.js_on_Visual_Studio.mp4" srclang="en" type="video/mp4">
    <track id="trackJA"  src="build2016breakout.vtt"  kind="captions" srclang="ja" label="Closed Captions" default>
</video>

Azure Searchによる全文検索

デモページ上部にある検索窓にキーワードを入力してGoボタンを押すとビデオコンテンツの字幕データを全文検索してキーワードにマッチしたテキストとその表示時間に絞り込むことができる。ここでは全文検索エンジンにAzure Searchを使用し、Azure Media Indexer 2 (Preview)より抽出された字幕データを解析して字幕表示時間とその対応テキストを1ドキュメントレコードとしてAzure Searchにインジェストしてその生成されたインデックスに対してキーワードを元に全文検索することで実現している。字幕データ検索用のインデックススキーマは次のように字幕表示時間とその対応テキストをレコード単位となるように定義している。

{
    "name": "stt",
    "fields": [
        { "name":"id", "type":"Edm.String", "key": true, "searchable": false, "filterable":false, "facetable":false },
        { "name":"contentid", "type":"Edm.String","searchable": false, "filterable":true, "facetable":false },
        { "name":"beginsec", "type":"Edm.Int32", "searchable": false, "filterable":false, "sortable":true, "facetable":false },
        { "name":"begin", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"end", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"caption", "type":"Edm.String", "searchable": true, "filterable":false, "sortable":false, "facetable":false, "analyzer":"en.microsoft" }
     ]
}

デモデータ作成手順

GithubプロジェクトページVideo-STT-Search-Pythonの1. Preparationと2. Batch executionを実施いただければ字幕データ*.vttファイルが生成され、そのテキストがAzure Searchに格納されてデモページ表示のための準備は完了する。最後に表示用のページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlとsearch.jsの変更のみでいけるはず。

本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。

Enjoy Video Speech-to-text demo!

Azure Media Servicesには一度に返却できるアセット情報(コレクション)の数に1000という制限があることは意外と知られていない。Azure Media Servicesでアセット一覧取得となるとほとんどの方がAzure公式ドキュメントにあるようにCloudMediaContextインスタンスのAssets(IAssetのリスト)を単純にループでまわすような記述をしているのではないかと推測するがそれだと後々問題になってくる。既に1000件以上のアセットがアップされている方は当然ながら、アセット数が少ない人についても下記のように1000件ずつもしくはそれ以下の数ずつAzure Media Servicesより取得してIAssetリストをループでまわすように実装しておいたほうが安全かと。

MediaServicesCredentials credentials = new MediaServicesCredentials(
                                    _accountName, _accountKey);
CloudMediaContext _context = new CloudMediaContext(credentials);

int selectlimit = 1000;
int offset = 0;
int selectposition = 0;
Console.WriteLine("Assets Total Count:" + _context.Assets.Count());
while (true)
{
    foreach (IAsset asset in _context.Assets.Skip(offset).Take(selectlimit))
    {
        selectposition++;
        Console.WriteLine("Asset ID: " + asset.Id);
        Console.WriteLine("Asset Name: " + asset.Name);
        Console.WriteLine("Asset LastModified: " + asset.LastModified);
    }
    if (selectposition == selectlimit)
    {
        offset += selectlimit;
        selectposition = 0;
    }
    else
    {
        break;
    }
}

サンプルコード
https://github.com/yokawasa/azure-samples/tree/master/ams-list-assets