- PVSM.RU - https://www.pvsm.ru -

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

Добрый день всем, кто нашел в себе силы для того, чтобы заглянуть на Хабр в последнюю рабочую неделю этого года! На этот раз я хотел бы поделиться с вами опытом использования сервисов для работы с мультимедиа контентом, предоставляемого облачными провайдерами. Чтобы процесс был более интересным мы рассмотрим два облачных провайдера: Windows Azure Media Services и Amazon Elastic Transcoder. После этого конечно же не забудем их сравнить! Итак, поехали!

Входные данные

Пусть входными данными для нас будет являться видео файл снятый с помощью мобильного устройства в формате 720p (Android). Его длительность равна 24 секундам, а размер 13 Мб. Мы хотим его конвертировать в формат 480p.

Базовый интерфейс

Итак, будем создавать новый Solution в Visual Studio. Предположим, что клиент для работы с каждым облачным провайдером должен реализовывать какую-то базовую функциональность. Чтобы, к примеру, мы могли легко заменить использование Windows Azure Media Services на Amazon Elastic Transcoder. Поэтому объявим базовый интерфейс:
public interface IVideoConverter
{
void Convert(string sourceFile, string destinationFile);

void UploadFile(string localFile);

void DownloadFile(string localFile);

void WaitForConversionToComplete();
}

Каждый клиент, реализующий этот интерфейс, должен уметь:

  • UploadFile – загружать файл с локального хранилища в облако;
  • DownloadFile – скачивать перекодированный файл из облачного хранилища в локальное;
  • Convert – собственно уметь перекодировать файл из одного формата в другой;
  • WaitForConversionToComplete – ожидать результатов выполнения операции кодирования.

Общий принцип работы с клиентом будет выглядеть следующим образом:
IVideoConverter client = new КлассРеализующийIVideoConverter();
client.Convert(“путь_к_исходному_файлу”, “путь_к_результирующему_файлу”);

Соответственно метод Convert в псевдокоде будет выглядеть так:
public void Convert(string sourceFile, string destinationFile)
{
// Загрузить файл
UploadFile(sourceFile);

// Начать кодирование
ПерекодироватьВидео();

// Дождаться результатов
WaitForConversionToComplete();

// Скачать перекодированный файл
DownloadFile(destinationFile);
}

Windows Azure Media Services

Начнем с реализации клиента для работы с Windows Azure Media Services. Прежде чем начать писать код, нам необходимо создать новый endpoint для работы с этим сервисом Windows Azure. Для этого заходим в Windows Azure Management Portal и выбираем New -> App Services -> Media Service -> Quick Create.

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

Нам необходимо задать имя нового сервиса (Name), регион (Region), в котором будут выделены мощности, аккаунт хранилища (Storage Account), а также подписку (Subscription) в рамках которой мы хотим использовать Windows Azure Media Services услугу.

Теперь для работы с сервисом нам необходимо получить Account Name и Access Key. Для этого перейдите в раздел Media Services портала управления Windows Azure и нажмите кнопку Manage Keys.

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

После чего, в появившемся окне, нам необходимо скопировать значения Account Name и Primary Access Key.

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

Скопированные значения мы определим в константах нашего класса, работающего с Windows Azure Media Services:
public class MediaServicesClient : IVideoConverter
{
private const string AccountName = "MEDIA_SERVICE_NAME";
private const string AccessKey = "MEDIA_SERVICE_KEY";
}

Итак, прежде чем перейти непосредственно к написаю кода соответствующего класса, нам необходимо подключить сборки Windows Azure Media Services SDK. Для этого воспользуемся пакетным менеджером NuGet. В контекстном меню нашего проекта выбираем пункт “Manage NuGet Packages…”. Ищем и устанавливаем соответствующий пакет:

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

Базовым объектом для работы с Windows Azure Media Services является MediaContext. По аналогии с DataContext в Entity Framework. В конструкторе класса создадим его, используя AccountName и AccessKey:
public MediaServicesClient()
{
_mediaContext = new CloudMediaContext(AccountName, AccessKey);
}

Этот объект позволит нам работать со всеми сущностями, предоставляемыми Windows Azure Media Services.

Первая сущность, которая будет нам необходима – это Media Processor. Все задачи (Tasks), которые мы посылаем на обработку Windows Azure Media Services должны быть обработаны определенным типом процессора. Все возможные варианты процессоров представлены здесь [1]. Наc же интересует Windows Azure Media Encoder. Этот процессор отвечает непосредственно за кодирование видеопотока в различные форматы. Добавим получение соответствующего процессора в наш конструктор:
private const string MediaProcessorName = "Windows Azure Media Encoder";

public MediaServicesClient()
{
...
_mediaProcessor = GetMediaProcessor();
}

private IMediaProcessor GetMediaProcessor()
{
return _mediaContext.MediaProcessors.Where
(x => x.Name == MediaProcessorName)
.ToList()
.First();
}

Также необходимо создать так называемый Asset – описание сущностей, которые будут использованы как входные или выходные параметры для процессора. В данном объекте будут храниться ссылки на используемый аккаунт хранилища, ссылки на файлы предназначенные для обработки и т.д. Создадим такой объект. Он будет хранить входные параметры, то есть, ссылки на файлы предназначенные для кодирования в нужный нам формат.
private const string InputAssetName = "MediaServices_InputAsset";

private readonly IAsset _inputAsset;

public MediaServicesClient()
{
...
_inputAsset = CreateInputAsset();
}

private IAsset CreateInputAsset()
{
return _mediaContext.Assets.Create(InputAssetName, AssetCreationOptions.None);
}

Все задачи кодирования (Tasks) выполняются в рамках какого-то задания (Job). Поэтому нам необходимо создать такой объект:
private const string JobName = "MediaServices_Job";

private readonly IJob _job;

_job = CreateEncodingJob();

private IJob CreateEncodingJob()
{
return _mediaContext.Jobs.Create(JobName);
}

И наконец необходимо связать все сущности, что мы создали. Создать соответствующие задачи по перекодированию одного видео в другого. Для этого объявим еще один метод, который будет вызываться непосредственно перед запуском задания (Job) на кодирование:
private const string PresetName = "H264 Broadband SD 16x9";

private void CreateTask()
{
var task = _job.Tasks.AddNew(
TaskName,
_mediaProcessor,
PresetName,
TaskOptions.ProtectedConfiguration);

task.InputAssets.Add(_inputAsset);
task.OutputAssets.AddNew(OutputAssetName, AssetCreationOptions.None);
}

Здесь следует обратить внимание на имя Preset, которое мы задаем. Это указание в какой именно формат мы хотим перекодировать наше видео. Список всех возможных вариантов можно найти здесь [2]. Согласно условию – мы будем кодировать исходное видео в формат 480p.

Таким образом, создав несколько задач (Tasks) для кодирования в разные форматы, можно использовать один исходный файл, допустим снятый в 1080р.

Итак, все методы, которые специфичные для работы с Windows Azure Media Services мы реализовали. Перейдем к реализации интерфейса IVideoConverter.

Поскольку Windows Azure Media Services работает в облаке, прежде чем запускать операцию кодирования, необходимо загрузить нужные файлы в хранилище. Этим в нашем интерфейсе занимается метод UploadFile. Собственно его реализация:
public void UploadFile(string localFile)
{
var fileName = Path.GetFileName(localFile);

var assetFile = _inputAsset.AssetFiles.Create(fileName);
assetFile.Upload(localFile);
}

Будем считать, что имя файла и будет ключом для доступа к объекту в хранилище. То есть все объекты будут храниться в корневом контейнере хранилища. Используя Asset для входных параметров добавляем ссылку на новый объект (имя файла в хранилище) и собственно говоря загружаем этот файл непосредственно в хранилище, используя метод Upload, объекта AssetFile.

Соответственно метод выгрузки файла из хранилища будет похожим:
public void DownloadFile(string localFile)
{
var outputAsset = _job.OutputMediaAssets.Single();
var outputFile = outputAsset.AssetFiles.ToList().Single(x => x.Name.Contains(".mp4"));

outputFile.Download(localFile);
}

Поскольку у нас только один выходной параметр (собственно говоря выходной Asset), то в коллекции OutputMediaAssets, соответствующего Job, получаем ссылку на единственный объект.
Кроме выходного файла c расширением mp4, Asset содержит файлы метаданных о процессе кодирования. Нам необходимо скачать именно mp4 файл. Собственно говоря, что мы и делаем с помощью метода Download, соответствующего AssetFile объекта.

Теперь реализуем метод, который будет запускать кодирование и ожидать результатов его выполнения:
public void WaitForConversionToComplete()
{
_job.StateChanged += JobOnStateChanged;

_job.Submit();

_job.GetExecutionProgressTask(CancellationToken.None).Wait();
}

Объект Job предоставляет нотификацию об изменении своего состояния с помощью соответствующих событий. Подпишемся на это событие:
private void JobOnStateChanged(object sender, JobStateChangedEventArgs state)
{
switch (state.CurrentState)
{
case JobState.Finished:
{
Console.WriteLine("Conversion complete!");
break;
}
case JobState.Queued:
case JobState.Scheduled:
case JobState.Processing:
{
Console.WriteLine("Conversion in progress...");
break;
}
case JobState.Canceled:
case JobState.Canceling:
case JobState.Error:
{
Console.WriteLine("An error has been occured during the job execution!");
break;
}
}
}

Затем отсылаем это задание на обработку, выполняя метод Submit. И ждем пока выполняемая задача завершится.

Таким образом единственный метод, оставшийся нереализованным – это Convert. Этот метод по сути будет просто вызывать ранее реализованные методы в соответствующем порядке. Его реализация:
public void Convert(string sourceFile, string destinationFile)
{
Console.WriteLine("Uploading the source file...");
UploadFile(sourceFile);

Console.WriteLine("Creating processing task...");
CreateTask();

Console.WriteLine("Starting conversion...");
WaitForConversionToComplete();

Console.WriteLine("Downloading converted file...");
DownloadFile(destinationFile);
}

Как мы видим, все довольно просто:

  1. Загрузили файл;
  2. Создали задачу на кодирование;
  3. Отправили задание на выполнение и дождались результатов;
  4. Скачали полученный файл.

В результате, вызвав метод Convert допустим в консольном приложении, мы получим следующий результат:

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

Сравним исходный и полученный файлы:

Windows Azure Media Services vs. Amazon Elastic Transcoder. Часть 1: Windows Azure Media Services

На этом реализация клиента для работы с Windows Azure Media Services завершена. В следующем году мы напишем клиент для работы с Amazon Elastic Transcoder. Не переключайтесь! Всем удачной рабочей недели и с наступающим!

Автор: RisingStar

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/windows-azure/51388

Ссылки в тексте:

[1] здесь: http://msdn.microsoft.com/en-us/library/windowsazure/jj129580.aspx

[2] здесь: http://msdn.microsoft.com/en-us/library/windowsazure/jj129582.aspx

[3] Источник: http://habrahabr.ru/post/207018/