Опубликован: 10.04.2013 | Доступ: свободный | Студентов: 440 / 9 | Длительность: 16:52:00
Специальности: Программист
Лекция 6:

Списки воспроизведения

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

Манипуляция аудио и видео

Как и при работе с изображения, если все, что нам нужно – это загрузить содержимое StorageFile в аудио- или видеоэлемент, мы можем просто передать этот StorageFile в URL.createObjectUrl и пприсвоить результат атрибуту src. Похожим образом, если нам нужны исходные данные, мы можем просто использовать методы StorageFile.openAsync или openReadAsync для получения файлового потока.

Честно говоря, открытие файла, это, вероятнее всего, самое сложное, что вам придется делать в JavaScript с исходными аудио- или видеоданными, если вообще придется этим пользоваться. В то время, как процесс обработка изображений находится где-то на грани приемлемости в окружении JavaScript, обрабатывать аудио, и особенно видео, лучше всего в высокопроизводительных DLL C++. На самом деле, легко доступны множесто платформенно нейтральных библиотек C++ сторонних разработчиков для подобных целей, которые вы сможете легко включить в состав подобных DLL. В подобном случае вы можете просто позволить DLL открыть нужный файл.

Тем не менее, WinRT предоставляет средства для перекодирования (конвертации) различных мультимедиа-форматов и предоставляет модель расширения для пользовательских кодеков, эффектов и обработчиков схем. На самом деле, мы уже видели, как применять пользовательские видео эффекты в примере "Расширения мультимедиа" (http://code.msdn.microsoft.com/windowsapps/Media-extensions-sample-7b466096), и те же DLL можно использовать при кодировании, где все, что выполняет код JavaScript – это связывание вместе нужных компонентов (что он делает очень хорошо). Посмотрим как это делается, сначала на примере перекодирования видео, а затем – на примере пользовательского кодека.

Перекодирование

Перекодирование аудио и видео реализуется посредством класса Windows.Media.Transcoding.MediaTranscoder (http://msdn.microsoft.com/library/windows/apps/windows.media.transcoding.mediatranscoder.aspx), который поддерживает выходные форматы mp3 и wma для аудио, и mp4, wmv и m4a для видео. Процесс перекодирования позволяет вам применять эффекты, осуществлять обрезку композиций.

Перекодирование происходит либо из одного объекта StorageFile в другой, или из одного RandomAccessStream в другой, в каждом из случае это производится в соответствии с MediaEncodingProfile (http://msdn.microsoft.com/library/windows/apps/windows.media.mediaproperties.mediaencodingprofile.aspx). Для настройки операции перекодирования, вы вызываете методы prepareFileTranscodeAsync (http://msdn.microsoft.com/library/windows/apps/windows.media.transcoding.mediatranscoder.preparefiletranscodeasync.aspx) или prepareStreamTranscodeAsync объекта MediaTranscoder, которые возвращают объект PrepareTranscodeResult (http://msdn.microsoft.com/library/windows/apps/windows.media.transcoding.preparetranscoderesult.aspx). Он представляет собой операцию, которая готова к работе, но обработка не начинается, пока вы не вызовете его метод transcodeAsync. В JavaScript, подобный результат является promise-объектом, который позволяет вам предоставлять обработчики завершения и выполнения для отдельной операции, а так же позволяет комбинировать операции с помощью WinJS.Promise.join. Это позволяет сначала настроить операции, а потом запустить их выполнение, что полезно для пакетной обработки и выполнения автоматической отправки на сервисы наподобие YouTube, пока вы спите! (В подобное время я вытаскиваю упаковку льда из морозилки и кладу ее под мой ноутбук из-за его плохой системы охлаждения)

Пример "Перекодирование мультимедиа" (http://code.msdn.microsoft.com/windowsapps/Media-Transcode-Sample-f7ba5269) показывает нам пару сценариев перекодирования. В Сценарии 1 (js/presets.js) мы можем выбрать видеофайл, задать целевой формат, выбрать профиль перекодирования и предоставить компьютеру возможность сделать свою работу (информация о продвижении операции предоставляется), как показано на рис. 6.4.

Пример перекодирования мультимедиа обрабатывает клип с моим двухлетним сыном, который исследует измерительную рулетку

Рис. 6.4. Пример перекодирования мультимедиа обрабатывает клип с моим двухлетним сыном, который исследует измерительную рулетку

Код, который выполняется, когда вы нажимаете на кнопку Transcode (Перекодировать) приведен ниже (кое-что опущено; в примере использованы вложенные promise-вызовы, что не рекомендуется, если вам нужна обработка ошибок, этот код поглощает любые исключения, которые происходят до вызова transcodeAsync):

function onTranscode() {	
// Создадим объект для перекодирования.	
var transcoder = null;	
transcoder = new Windows.Media.Transcoding.MediaTranscoder();

// Получим профиль перекодирования.
getPresetProfile(id("profileSelect"));

// Создадим выходной файл и начнем перекодировку.	
var videoLib = Windows.Storage.KnownFolders.videosLibrary;	
var createFileOp = videoLib.createFileAsync(g_outputFileName,	
Windows.Storage.CreationCollisionOption.generateUniqueName);

createFileOp.done(function (ofile) {	
g_outputFile = ofile;	
g_transcodeOp = null;	
var prepareOp = transcoder.prepareFileTranscodeAsync(g_inputFile, g_outputFile,
g_profile);	

prepareOp.done(function (result) {
if (result.canTranscode) {
g_transcodeOp = result.transcodeAsync();
g_transcodeOp.done(transcodeComplete, transcoderErrorHandler, transcodeProgress);
} else {
transcodeFailure(result.failureReason);
}
}); // prepareOp.done 
id("cancel").disabled = false;
}); // createFileOp.done
}
 

Метод getPresentProfile получает подходящий объект профиля, соответствующий параметрам, выбранным в приложении. Для параметров, выбранных на рис. 6.4 (WMV и WVGA) мы используем следующие части этой функции:

function getPresetProfile(profileSelect) {	
g_profile = null;	
var mediaProperties = Windows.Media.MediaProperties;
var videoEncodingProfile;	

switch (profileSelect.selectedIndex) {
// Остальные варианты опущены 
case 2:
videoEncodingProfile = mediaProperties.VideoEncodingQuality.wvga;
break;
}
if (g_useMp4) {
g_profile = mediaProperties.MediaEncodingProfile.createMp4(videoEncodingProfile);
} else {
g_profile = mediaProperties.MediaEncodingProfile.createWmv(videoEncodingProfile);
}
}
 

В Сценарии 2 всегда используется WVGA-коодирование, но здесь вы можете установить необходимые значения для размерностей видео, частоты кадров, битрейта аудио и видео, настроить аудиоканалы и аудиосэмплинг. Данные параметры используются в getCustomProfile (js/custom.js), просто конфигурируя параметры профиля после его создания:

function getCustomProfile() {	
if (g_useMp4) {	
g_profile = Windows.Media.MediaProperties.MediaEncodingProfile.createMp4(
Windows.Media.MediaProperties.VideoEncodingQuality.wvga);	
} else {	
g_profile = Windows.Media.MediaProperties.MediaEncodingProfile.createWmv(
Windows.Media.MediaProperties.VideoEncodingQuality.wvga);	
}	

// Берем значения настроек из элементов пользовательского интерфейса 
g_profile.audio.bitsPerSample = id("AudioBPS").value; 
g_profile.audio.channelCount = id("AudioCC").value; 
g_profile.audio.bitrate = id("AudioBR").value; 
g_profile.audio.sampleRate = id("AudioSR").value; 
g_profile.video.width = id("VideoW").value; 
g_profile.video.height = id("VideoH").value; 
g_profile.video.bitrate = id("VideoBR").value; 
g_profile.video.frameRate.numerator = id("VideoFR").value; 
g_profile.video.frameRate.denominator = 1;
}
 

И, в завершении, Сценарий 3 похож на Сценарий 1, но позволяет вам задать время начала и конца записи для ее обрезки, которые затем сохраняются в свойствах перекодировщика trimStartTime и trimStopTime (js/trim.js):

transcoder = new Windows.Media.Transcoding.MediaTranscoder();
transcoder.trimStartTime = g_start;
transcoder.trimStopTime = g_stop;
 

Хотя это и не показано в примре, вы можете применять эффекты при операции перекодирования, используя методы перекодировника addAudioEffect и addVideoEffect.

Пользовательские кодеры/декодеры и обработчики схем

Очевидно то, что в мире гораздо больше аудио- и видеоформатов, чем поддерживается в исходной поставке Windows, поэтому WinRT предоставляет механизм расширения, позволяющий работать с пользовательскими объектами битовых потоков, источниками мультимедийных данных, пользовательскими кодеками и эффектами. Важно снова отметить, что все эти расширения доступны только самому приложению и не доступны другим приложениям. Более того, Windows всегда предпочитает встроенные компоненты пользовательским, а это означает, что вам не следует впустуют тратить время на разработку нового декодера mp3, так как он никогда не будет использован.

Как было сказано ранее, о пользовательских форматах изображений, эти вопросы ведут в весьма обширную область вокруг Windows Media Foundation (WMF) SDK (http://msdn.microsoft.com/library/ms694197.aspx). И WinRT лишь предоставляет оболочку для этого, поэтому изучение WMF существенно в этих вопросах, и это занятие не для слабонервных!

Аудио- и видеорасширения объявляются в манифесте приложения, вам понадобится непосредственно править XML. Как можно увидеть в примере "Расширения мультимедиа" (http://code.msdn.microsoft.com/windowsapps/Media-extensions-sample-7b466096), для каждой DLL в решении объявление выглядит так:

 <Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>	
<Path>MPEG1Decoder.dll</Path>	
<ActivatableClass ActivatableClassId="MPEG1Decoder.MPEG1Decoder"
ThreadingModel="both" />	
</InProcessServer>	
</Extension>	

ActivatableClassId это то, как идентифицируется расширение при вызовах WinRT APIs, что ясно отражается в манифесте для каждой DLL, которая должна быть загружена.

В зависимости от использования расширения, вам может понадобиться зарегистрировать его в WinRT посредством методов Windows.Media.MediaExtensionManager: registerAudio[Decoder | Encoder], registerByteStreamHandler (потоки мультимедиа), registerSchemeHandler (источники мультимедиа/файлы-контейнеры), и registerVideo[Decoder | Encoder] . В сценарии 1 примера о расширениях мультимедиа (js/LocalDecoder.js), мы можем видеть, как задать пользовательский декодер для воспроизведения видео.

 воспроизведения видео.
var page = WinJS.UI.Pages.define("/html/LocalDecoder.html", {	
extensions: null,	
MFVideoFormat_MPG1: { value: "{3147504d-0000-0010-8000-00aa00389b71}" },
NULL_GUID: { value: "{00000000-0000-0000-0000-000000000000}" },	

ready: function (element, options) {
if (!this.extensions) {
// Добавьте здесь любой код инициализации
this.extensions = new Windows.Media.MediaExtensionManager();
// Зарегистрируем пользовательский ByteStreamHandler и пользовательский декодер. 
this.extensions.registerByteStreamHandler("MPEG1Source.MPEG1ByteStreamHandler",
".mpg", null);
this.extensions.registerVideoDecoder("MPEG1Decoder.MPEG1Decoder", this.MFVideoFormat_MPG1, this.NULL_GUID);
}

// ...

Здесь CLSID MPEG1Source.MPEG1ByteStreamHandler реализован в одной DLL (смотрите проект C++ MPEG1Source в решении), а CLSID MPEG1Decoder.MPEG1.Decoder реализован в другой (C++ проект MPEG1Decoder).

Сценарий 2, в свою очередь, показывает использование пользовательского обработчика схемы, где обработчик (в проекте C++ GeometricSource) генерирует видеокадры в процессе выполнения программы. Притягательная возможность, но находящаяся за пределами тем данного курса.

Эффекты, как мы можем видеть, довольно просто использовать, если у вас есть реализация эффекта, просто передайте ее CLSID методу наподобие msInsertVideoEffect и msInsertAudioEffect видео или аудиоэлемента. Так же вы можете применить эффект в процессе перекодирования, в методах addAudioEffect и addVideoEffect класса MediaTranscoder. То же самое справедливо и для процесса захвата мультимедийных данных, который мы сейчас рассмотрим.

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
Вадик Елетин
Вадик Елетин
Россия, г. Санкт-Петербург
Николай Жигульский
Николай Жигульский
Россия, Тверь, Тверской государственный технический университет