Добрый день всем, кто нашел в себе силы для того, чтобы заглянуть на Хабр в последнюю рабочую неделю этого года! На этот раз я хотел бы поделиться с вами опытом использования сервисов для работы с мультимедиа контентом, предоставляемого облачными провайдерами. Чтобы процесс был более интересным мы рассмотрим два облачных провайдера: Windows Azure Media Services и Amazon Elastic Transcoder. После этого конечно же не забудем их сравнить! Итак, поехали!
Пусть входными данными для нас будет являться видео файл снятый с помощью мобильного устройства в формате 720p (Android). Его длительность равна 24 секундам, а размер 13 Мб. Мы хотим его конвертировать в формат 480p.
Итак, будем создавать новый Solution в Visual Studio. Предположим, что клиент для работы с каждым облачным провайдером должен реализовывать какую-то базовую функциональность. Чтобы, к примеру, мы могли легко заменить использование Windows Azure Media Services на Amazon Elastic Transcoder. Поэтому объявим базовый интерфейс:
Каждый клиент, реализующий этот интерфейс, должен уметь:
Общий принцип работы с клиентом будет выглядеть следующим образом:
Соответственно метод Convert в псевдокоде будет выглядеть так:
Начнем с реализации клиента для работы с Windows Azure Media Services. Прежде чем начать писать код, нам необходимо создать новый endpoint для работы с этим сервисом Windows Azure. Для этого заходим в Windows Azure Management Portal и выбираем New -> App Services -> Media Service -> Quick Create.
Нам необходимо задать имя нового сервиса (Name), регион (Region), в котором будут выделены мощности, аккаунт хранилища (Storage Account), а также подписку (Subscription) в рамках которой мы хотим использовать Windows Azure Media Services услугу.
Теперь для работы с сервисом нам необходимо получить Account Name и Access Key. Для этого перейдите в раздел Media Services портала управления Windows Azure и нажмите кнопку Manage Keys.
После чего, в появившемся окне, нам необходимо скопировать значения Account Name и Primary Access Key.
Скопированные значения мы определим в константах нашего класса, работающего с Windows Azure Media Services:
Итак, прежде чем перейти непосредственно к написаю кода соответствующего класса, нам необходимо подключить сборки Windows Azure Media Services SDK. Для этого воспользуемся пакетным менеджером NuGet. В контекстном меню нашего проекта выбираем пункт “Manage NuGet Packages…”. Ищем и устанавливаем соответствующий пакет:
Базовым объектом для работы с Windows Azure Media Services является MediaContext. По аналогии с DataContext в Entity Framework. В конструкторе класса создадим его, используя AccountName и AccessKey:
Этот объект позволит нам работать со всеми сущностями, предоставляемыми Windows Azure Media Services.
Первая сущность, которая будет нам необходима – это Media Processor. Все задачи (Tasks), которые мы посылаем на обработку Windows Azure Media Services должны быть обработаны определенным типом процессора. Все возможные варианты процессоров представлены здесь. Наc же интересует Windows Azure Media Encoder. Этот процессор отвечает непосредственно за кодирование видеопотока в различные форматы. Добавим получение соответствующего процессора в наш конструктор:
Также необходимо создать так называемый Asset – описание сущностей, которые будут использованы как входные или выходные параметры для процессора. В данном объекте будут храниться ссылки на используемый аккаунт хранилища, ссылки на файлы предназначенные для обработки и т.д. Создадим такой объект. Он будет хранить входные параметры, то есть, ссылки на файлы предназначенные для кодирования в нужный нам формат.
Все задачи кодирования (Tasks) выполняются в рамках какого-то задания (Job). Поэтому нам необходимо создать такой объект:
И наконец необходимо связать все сущности, что мы создали. Создать соответствующие задачи по перекодированию одного видео в другого. Для этого объявим еще один метод, который будет вызываться непосредственно перед запуском задания (Job) на кодирование:
Здесь следует обратить внимание на имя Preset, которое мы задаем. Это указание в какой именно формат мы хотим перекодировать наше видео. Список всех возможных вариантов можно найти здесь. Согласно условию – мы будем кодировать исходное видео в формат 480p.
Таким образом, создав несколько задач (Tasks) для кодирования в разные форматы, можно использовать один исходный файл, допустим снятый в 1080р.
Итак, все методы, которые специфичные для работы с Windows Azure Media Services мы реализовали. Перейдем к реализации интерфейса IVideoConverter.
Поскольку Windows Azure Media Services работает в облаке, прежде чем запускать операцию кодирования, необходимо загрузить нужные файлы в хранилище. Этим в нашем интерфейсе занимается метод UploadFile. Собственно его реализация:
Будем считать, что имя файла и будет ключом для доступа к объекту в хранилище. То есть все объекты будут храниться в корневом контейнере хранилища. Используя Asset для входных параметров добавляем ссылку на новый объект (имя файла в хранилище) и собственно говоря загружаем этот файл непосредственно в хранилище, используя метод Upload, объекта AssetFile.
Соответственно метод выгрузки файла из хранилища будет похожим:
Поскольку у нас только один выходной параметр (собственно говоря выходной Asset), то в коллекции OutputMediaAssets, соответствующего Job, получаем ссылку на единственный объект.
Кроме выходного файла c расширением mp4, Asset содержит файлы метаданных о процессе кодирования. Нам необходимо скачать именно mp4 файл. Собственно говоря, что мы и делаем с помощью метода Download, соответствующего AssetFile объекта.
Теперь реализуем метод, который будет запускать кодирование и ожидать результатов его выполнения:
Объект Job предоставляет нотификацию об изменении своего состояния с помощью соответствующих событий. Подпишемся на это событие:
Затем отсылаем это задание на обработку, выполняя метод Submit. И ждем пока выполняемая задача завершится.
Таким образом единственный метод, оставшийся нереализованным – это Convert. Этот метод по сути будет просто вызывать ранее реализованные методы в соответствующем порядке. Его реализация:
Как мы видим, все довольно просто:
В результате, вызвав метод Convert допустим в консольном приложении, мы получим следующий результат:
Сравним исходный и полученный файлы:
На этом реализация клиента для работы с 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.
Нам необходимо задать имя нового сервиса (Name), регион (Region), в котором будут выделены мощности, аккаунт хранилища (Storage Account), а также подписку (Subscription) в рамках которой мы хотим использовать Windows Azure Media Services услугу.
Теперь для работы с сервисом нам необходимо получить Account Name и Access Key. Для этого перейдите в раздел Media Services портала управления Windows Azure и нажмите кнопку Manage Keys.
После чего, в появившемся окне, нам необходимо скопировать значения Account Name и Primary Access Key.
Скопированные значения мы определим в константах нашего класса, работающего с 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 является MediaContext. По аналогии с DataContext в Entity Framework. В конструкторе класса создадим его, используя AccountName и AccessKey:
public MediaServicesClient()
{
_mediaContext = new CloudMediaContext(AccountName, AccessKey);
}
Этот объект позволит нам работать со всеми сущностями, предоставляемыми Windows Azure Media Services.
Первая сущность, которая будет нам необходима – это Media Processor. Все задачи (Tasks), которые мы посылаем на обработку Windows Azure Media Services должны быть обработаны определенным типом процессора. Все возможные варианты процессоров представлены здесь. На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, которое мы задаем. Это указание в какой именно формат мы хотим перекодировать наше видео. Список всех возможных вариантов можно найти здесь. Согласно условию – мы будем кодировать исходное видео в формат 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);
}
Как мы видим, все довольно просто:
- Загрузили файл;
- Создали задачу на кодирование;
- Отправили задание на выполнение и дождались результатов;
- Скачали полученный файл.
В результате, вызвав метод Convert допустим в консольном приложении, мы получим следующий результат:
Сравним исходный и полученный файлы:
На этом реализация клиента для работы с Windows Azure Media Services завершена. В следующем году мы напишем клиент для работы с Amazon Elastic Transcoder. Не переключайтесь! Всем удачной рабочей недели и с наступающим!
Продолжение...