Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Выразите себя – кодирование видеороликов с помощью Microsoft Expression Encoder 3 SDK
Адам Миллер
Один из моих самых любимых эпизодов — сцена в фильме, где Кларк Гризвулд — его роль в фильме «Рождество семейки придурков» («Christmas Vacation») исполняет актер Чеви Чейз (Chevy Chase), — оказывается запертым на своем чердаке при попытке спрятать там рождественские подарки. Чтобы согреться, он надевает розовые перчатки, зеленую шапку и меховую накидку, вытащенные из пыльного сундука. На дне сундука он обнаруживает кинопленки из семейного архива и, коротая время, просматривает их со слезами на глазах на старом кинопроекторе.
Домашние видеозаписи с тех пор сильно изменились, но перед людьми встает все та же проблема: как показывать свои записи семье и друзьям? Сайты вроде YouTube, Vimeo и Facebook позволяют легко сделать эти записи доступными для просмотра многим людям, но заливка на такие сайты видеозаписей высокой четкости с потоком хорошо за 100 Мб/мин требует слишком много времени. Все шансы за то, что ваше мобильное устройство, игровая приставка или домашний кинотеатр даже не сумеют воспроизвести файл с таким видеопотоком. Для решения этих проблем нужно преобразовать видео в другой формат. Этот процесс называют кодированием (encoding).
Об Expression Encoder
Инструмент кодирования видео от Microsoft, Expression Encoder 3, является частью семейства продуктов Expression для создания впечатляющих UI для настольных и веб-приложений. Expression Encoder поставляется в бесплатной и платной версиях; платная версия входит в состав как Expression Studio 3 Suite (599 долларов США), так и Expression Web 3 Suite (149 долларов США). Бесплатная версия не поддерживает кодирование в форматах Silverlight Smooth Streaming и H.264, а также использование видео формата H.264 в качестве источника, но она, тем не менее, позволяет кодировать в файлы Windows Media Video и содержит неплохой SDK. Многие из примеров кода в этой статье требуют наличия платной версии программы; тем не менее все примеры кода будут компилироваться и в бесплатной версии SDK. Просто при запуске скомпилированного кода вы получите исключение InvalidMediaException или FeatureNotAvailableException.
Если вы не готовы приобрести Expression Suite, вы можете начать работу с Expression Encoder, скачав бесплатную версию по ссылке microsoft.com/expression. Expression Suite также доступен по подписке на Expression через MSDN уровня Professional или на Visual Studio Professional через MSDN уровня Premium. Учтите, что 149 долларов США за приложение для профессионального кодирования видео с таким набором функций, широким спектром входных и выходных форматов — это практически бесплатно. Аналогичные решения в области кодирования видео могут стоить вплоть до 3000 долларов.
Какую бы версию вы ни выбрали, вы захотите установить Encoder 3 QFE. Он обеспечивает поддержку дополнительных типов файлов и устройств ввода, повышает скорость работы в определенных ситуациях и включает исправления ряда несущественных ошибок. Установщик QFE можно найти на странице Expression Encoder веб-сайта Microsoft Expression.
Поддерживаемые форматы
Поддерживаются следующие входные форматы видео:
- Windows Media Video (.wmv);
- DVD-видео (.vob);
- MPEG (.mpg, .mpeg);
- Audio Video Interleave (.avi);
- Microsoft Digital Video Recording (.dvr-ms).
Платная версия дополнительно поддерживает следующие форматы (плюс целый ряд других форматов):
- MPEG-4 (.mp4, .m4v);
- Quicktime (.mov);
- AVC HD (.mts);
- Mobile Device Video (.3gp, .3g2).
По большей части Expression Encoder поддерживает любой медийный файл, который может быть воспроизведен Windows Media Player. Если вам нужна поддержка еще большего числа форматов (и возможность их проигрывания в Windows Media Player), вы можете установить пакет кодеков вроде K-Lite Codec Pack (codecguide.com) или Community Combined Codec Pack (cccp-project.net). Оба пакета базируются на проекте ffdshow с открытым исходным кодом и добавят поддержку Flash-файлов с кодированием VP6 (.flv), видео H.264 в контейнере Matroska (.mkv) и видеофайлы Ogg (.ogg).
Бесплатная версия Expression Encoder поддерживает в качестве выходного кодека только Microsoft VC-1. Однако это все равно позволяет кодировать видео для Silverlight (только с одним битрейтом), Xbox 360, Zune и Zune HD. Кроме того, кодек VC-1 вовсе не плох: он обеспечивает сжатие не хуже (а иногда и лучше), чем H.264. Обновление до платной версии даст вам выходные форматы Silverlight Smooth Streaming (с несколькими битрейтами) и H.264, т. е. вы сможете кодировать видео для воспроизведения на iPhone, PS3, Flash-плеере (версия 10 поддерживает H.264/.mp4) и множестве других устройств.
Кодирование номер 101
Поддержка определенных устройств вывода требует изменения некоторых параметров профиля видео, поэтому вы должны понимать основы кодирования видео. Перекодирование — это фактически процесс декомпрессии видео и его повторное сжатие с использованием другого кодека или с ручным изменением таких атрибутов, как размер, соотношение сторон или скорости кадров. Хотя существуют методы сжатия без потерь, они применяются редко, так как получаемые в итоге файлы все равно остаются слишком большими. Поэтому, чтобы уменьшить объем пространства, необходимого для хранения видео (и соответственно ускорить его передачу), для сжатия и декомпрессии видео используют некий алгоритм, или кодек. После этого сжатый видеопоток сохраняется согласно спецификации контейнера (например, WMV или MP4). Контейнеры и кодеки зачастую не образуют эксклюзивных контрактов, поэтому, хотя H.264 является наиболее распространенным кодеком для контейнера MP4, можно использовать и другие кодеки.
Битрейт (bitrate), выражаемый в Кбит/с, определяет, сколько данных требуется для хранения сжатого видео. Уменьшение битрейта сообщает кодировщику сжимать видео с более высокой степенью компрессии, что приводит к ухудшению качества видео. Существуют разные способы, с помощью которых можно указывать кодировщику, как определять битрейт видео. Самый простой — использовать постоянный битрейт (constant bitrate, CBR), при котором кодировщик использует одинаковый объем данных для каждой секунды видео. Переменный битрейт (variable bitrate, VBR) позволяет сообщить кодировщику, каким должен быть общий битрейт конечного файла, но разрешить ему самостоятельно увеличивать или понижать битрейт для конкретного раздела видео, исходя из необходимого для него объема данных. Переменный ограниченный битрейт аналогичен неограниченному VBR с тем исключением, что вы указываете не только средний битрейт, но и максимальный, который нельзя превышать.
Переменный ограниченный битрейт полезен при кодировании видео Silverlight Smooth Streaming. Он гарантирует, что битрейт не превысит пропускную способность клиентского соединения и не вынудит клиент запрашивать поток более низкого качества. Для CBR и VBR степень сжатия определяется заданием общего размера файла видео.
В качестве альтернативы вы можете сообщить кодировщику использовать VBR с учетом заданного качества. Вместо того чтобы указывать общий размер файла, вы выбираете процент качества, который сохранится в декомпрессированном видео. В случае мультфильма для сохранения хорошего качества требуется меньше данных, чем для природных видов или фильмов в жанре «экшн». Поэтому, если у вас имеется высококачественный источник и вы хотите преобразовать его в другой формат с сохранением оптимального качества, подумайте о применении VBR с учетом заданного качества. Все эти определения — не более чем верхушка айсберга, но они являются основополагающими при выборе параметров вывода. Дополнительные определения кодирования еще будут встречаться в этой статье, так как они применяются к примерам кода.
Использование SDK
Чтобы следовать примерам кода, вам потребуется видео хорошего качества. Если у вас нет под рукой видео с высоким разрешением, вы можете взять некоторые HD-видеоролики по ссылке microsoft.com/windows/windowsmedia/musicandvideo/hdvideo/contentshowcase.aspx. Я воспользуюсь в качестве источника для своих примеров видеороликом Adrenaline Rush.
Установив Expression Encoder 3, создайте в Visual Studio новый проект C# Console Application. Добавьте ссылки на Microsoft.Expression.Encoder.dll и Microsoft.Expression.Encoder.Utilities.dll, находящиеся в \Program Files (x86)\Microsoft Expression\Encoder 3\SDK. Кроме того, вам понадобится добавить ссылку на WindowsBase, который вы найдете на вкладке .NET диалога Add References. Многие используемые мной классы размещены в пространстве имен Microsoft.Expression.Encoder, поэтому вставьте соответствующее выражение using.
Первым создается экземпляр объекта MediaItem. Его конструктор принимает строку как единственный параметр. Передайте путь к файлу, который вы используете в качестве источника в проекте кодирования:
MediaItem src = new MediaItem(@"C:\WMdownloads\AdrenalineRush.wmv");
Создание объекта MediaItem занимает одну-две секунды. SDK при этом выполняет «за кулисами» весьма приличный объем работы, собирая такую информацию об исходном видео, как его высота, ширина, скорость кадров (частота, с которой на экране должны отображаться индивидуальные изображения) и длительность. попутно собираются сведения и об аудиопотоке.
Затем вы создаете экземпляр класса Job (в котором всего один конструктор без параметров) и добавляете свой MediaItem в его список MediaItems. Класс Job выступает в роли диспетчера желательных форматов вывода (также называемых профилями):
Job job = new Job();
job.MediaItems.Add(src);
Теперь вам нужно сообщить объекту Job, какие профили аудио и видео следует использовать при кодировании; самый простой способ — выбрать один из профилей, определенных в UI. Чтобы создать видео, например для Zune HD, вы можете использовать пресет VC1ZuneHD:
job.ApplyPreset(Presets.VC1ZuneHD);
Наконец, укажите каталог вывода и запустите процесс кодирования:
job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();
Ваш файл Program.cs должен выглядеть примерно так, как показано на рис. 1.
Рис. 1. Создание видео для Zune HD
using Microsoft.Expression.Encoder;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
MediaItem src = new MediaItem
(@"C:\WMdownloads\AdrenalineRush.wmv");
Job job = new Job();
job.MediaItems.Add(src);
job.ApplyPreset(Presets.VC1ZuneHD);
job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();
}
}
}
Осталось сделать лишь одно, прежде чем запускать приложение: если вы используете 64-разрядную версию Windows, вам нужно модифицировать проект для компиляции под x86. В строке меню Visual Studio выберите Project | (Имя_проекта) Properties. В открывшемся диалоговом окне выберите вкладку Build и смените значение Platform Target с «Any CPU» на «x86».
Теперь вы готовы запустить приложение и создать видео, которое можно будет просматривать на Zune HD. Процесс кодирования займет несколько минут и будет очень сильно нагружать процессор. Кодирование видео значительно выигрывает от распараллеливания, поэтому на многоядерных процессорах эта операция будет выполнена намного быстрее.
В Expression Encoder также включены пресеты для кодирования под сетевые сервисы наподобие YouTube, Vimeo и Facebook. Видео с разрешением 720p, записанное моей цифровой камерой Panasonic Lumix DMC-ZS3, расходует 110 Мб на минуту видеозаписи. Преобразование видео с применением пресета YouTube HD (тоже с разрешением 720p) уменьшает этот объем до 16 Мб. Благодаря этому его можно гораздо эффективнее закачивать на сервис и хранить на локальном диске. Преобразование в файл .mp4 также делает его совместимым с многими другими программами редактирования видео.
Пользовательские настройки
Чтобы вручную создать такой же вывод, как и при использовании пресета VC1ZuneHD, вам пришлось бы написать код, показанный на рис. 2, чтобы задать профили видео и аудио. Чтобы скомпилировать код на рис. 2, вы должны добавить ссылки на Microsoft.Expression.Encoder.Utilities и System.Drawing. Также добавьте выражения using для Microsoft.Expression.Encoder.Profiles и System.Drawing. OutputFormat фактически указывает контейнер для выходного файла. Я сказал «фактически», потому что кодирование для Silverlight работает слегка иначе (как именно — я расскажу чуть позже).
Рис. 2. Параметры профилей видео и аудио для Zune HD
MediaItem src = new MediaItem(@"C:\WMdownloads\AdrenalineRush.wmv");
src.OutputFormat = new WindowsMediaOutputFormat();
src.OutputFormat.VideoProfile = new AdvancedVC1VideoProfile();
src.OutputFormat.VideoProfile.Bitrate = new
VariableConstrainedBitrate(1000, 1500);
src.OutputFormat.VideoProfile.Size = new Size(480, 272);
src.OutputFormat.VideoProfile.FrameRate = 30;
src.OutputFormat.VideoProfile.KeyFrameDistance = new TimeSpan(0, 0, 4);
src.OutputFormat.AudioProfile = new WmaAudioProfile();
src.OutputFormat.AudioProfile.Bitrate = new
VariableConstrainedBitrate(128, 192);
src.OutputFormat.AudioProfile.Codec = AudioCodec.WmaProfessional;
src.OutputFormat.AudioProfile.BitsPerSample = 24;
Job job = new Job();
job.MediaItems.Add(src);
job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();
VideoProfile задает применяемый видеокодек наряду с параметрами кодирования. Аналогично AudioProfile указывает аудиокодек вместе с параметрами. При конструировании VariableConstrainedBitrate первый параметр сообщает средний битрейт, а второй — максимальный. Параметр размера задает прямоугольник, в который должно умещаться конечное видео. Для видеоролика Adrenaline Rush я задал конечные размеры 480 × 272, чтобы сохранить соотношение сторон, но если бы я ввел 480 × 480, конечное видео все равно было бы 480 × 272.
Свойство KeyFrameDistance на рис. 2 относится к концепции кодирования видео, о которой я еще не упоминал. В большинстве случае при кодировании видео сохраняются лишь изменения между соседними кадрами, а не вся картинка каждого кадра. Ключевыми являются кадры, содержащие целое изображение. Этот код будет создавать ключевые кадры через каждые четыре секунды. Они будут создаваться и автоматически, когда в видеоролике обнаруживаются крупные изменения, например смена сцены, но вы все равно должны создавать их через заранее определенные интервалы для поддержки поиска нужных кадров в процессе воспроизведения видео.
Silverlight Smooth Streaming
Silverlight Smooth Streaming динамически переключает битрейт воспроизводимого медийного файла в зависимости от текущих условий в сети. Проект Smooth Streaming состоит из индивидуальных видеороликов, хранящихся в файлах .ismv, а также из файлов метаданных .ism и .ismc, которые поддерживают воспроизведение Smooth Streaming.
Чтобы создать проект Silverlight Smooth Streaming, нужно внести целый ряд изменений. Во-первых, измените значение KeyFrameDistance на две секунды. Видеоролик будет по-прежнему проигрываться, если оставить KeyFrameDistance равным четырем секундам, но воспроизведение может оказаться дерганым, когда проигрыватель будет переключать битрейты. Проигрыватель Silverlight будет запрашивать видео порциями длиной по две секунды, поэтому воспроизведение окажется более плавным, если в начале каждого запроса будет находиться ключевой кадр. Вам также понадобится добавить следующую строку:
src.OutputFormat.VideoProfile.SmoothStreaming = true;
Установив значение SmoothStreaming в true, вы сообщает кодировщику выводить видео в файлы .ismv и создавать файлы метаданных .ism и .ismc. При наличии только одного битрейта ваш проект на самом деле не будет Smooth Streaming, поэтому, чтобы создать несколько битрейтов выходного видео, вы должны добавить в VideoProfile несколько потоков данных. Для этого используйте код, аналогичный показанному на рис. 3.
Рис. 3. Добавление Silverlight Smooth Streaming
MediaItem src = new MediaItem(@"C:\WMdownloads\AdrenalineRush.wmv");
src.OutputFormat = new WindowsMediaOutputFormat();
src.OutputFormat.VideoProfile = new AdvancedVC1VideoProfile();
src.OutputFormat.VideoProfile.KeyFrameDistance = new TimeSpan(0, 0, 2);
src.OutputFormat.VideoProfile.SmoothStreaming = true;
src.OutputFormat.VideoProfile.Streams.Clear();
src.OutputFormat.VideoProfile.Streams.Add(new StreamInfo(new
VariableConstrainedBitrate(2000, 3000), new Size(1280, 720)));
src.OutputFormat.VideoProfile.Streams.Add(new StreamInfo(new
VariableConstrainedBitrate(1400, 1834), new Size(848, 476)));
src.OutputFormat.VideoProfile.Streams.Add(new StreamInfo(new
VariableConstrainedBitrate(660, 733), new Size(640, 360)));
src.OutputFormat.AudioProfile = new WmaAudioProfile();
src.OutputFormat.AudioProfile.Bitrate = new
VariableConstrainedBitrate(128, 192);
src.OutputFormat.AudioProfile.Codec = AudioCodec.WmaProfessional;
src.OutputFormat.AudioProfile.BitsPerSample = 24;
Job job = new Job();
job.MediaItems.Add(src);
job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();
Здесь в коде указаны три различных битрейта и масштабы для кодирования. Для оптимального качества размер видео необходимо сократить, поскольку битрейт сокращен. Указывая собственные битрейты, вы можете использовать настройки IIS Smooth Streaming в Expression Encoder 3 UI. Заметьте, что увеличить качество кодированием видео с более высоким разрешением, чем в исходном файле, нельзя. И вообще кодировать с более высоким, чем в источнике битрейтом имеет смысл только при использовании метода более слабой компрессии. Если SDK смог определить битрейт в исходном файле, он будет присутствовать в свойстве SourceVideoProfile, принадлежащем MediaItem:
int bitrate = ((ConstantBitrate)src.SourceVideoProfile.Bitrate).Bitrate;
Если SDK не удалось получить битрейт в исходном файле, вы можете примерно оценить его по размеру файла. Вот формула:
Примерный битрейт в Кбит/с = (размер файла в Кб * 8 / длительность видео в секундах) – битрейт аудио в Кбит/с
Чтобы получить размер исходного файла, используйте класс System.IO.FileInfo, а с помощью SDK можно узнать длительность (свойство MediaItem.FileDuration) и, возможно, битрейт аудиопотока. Если вы не знаете битрейт аудио, используйте для оценки 128 или 160 (в большинстве случаев битрейты аудиопотоков колеблются в пределах 64–192); вы также можете узнать битрейт аудио в окне свойств Windows Media Player (нажмите Alt, чтобы появилась строка меню, а затем выберите File | Properties).
Отслеживание процесса кодирования
Поскольку кодирование может занимать часы, полезно иметь возможность отслеживать его прогресс. SDK предоставляет простой способ мониторинга процесса кодирования через событие, для которого вы можете добавить обработчик:
job.EncodeProgress += new EventHandler<EncodeProgressEventArgs>(OnProgress);
Добавьте примерно такой метод для обработки этого события:
static void OnProgress(object sender, EncodeProgressEventArgs e)
{
Console.Clear();
Console.WriteLine((100 * (e.CurrentPass - 1) + e.Progress) / e.TotalPasses + "%");
}
Многопроходное кодирование — новая концепция, представленная в этом примере кода. При кодировании с переменным битрейтом процесс выполняется в два этапа, называемых проходами. На первом проходе исходное видео анализируется, чтобы определить, какие части самые сложные и получат преимущество от более высокого битрейта. На втором проходе видео кодируется с использованием информации, полученной на первом проходе. Таким образом, если вы применяете постоянный битрейт, вам незачем использовать свойство CurrentPass или TotalPasses класса EncodeProgressEventArgs.
Комбинирование видеороликов
Если вам нужно кодировать только часть видеоролика или скомбинировать несколько видеороликов в один, соответствующая поддержка в SDK есть. Чтобы модифицировать время начала и конца исходного медийного элемента (source media item), вы можете изменить свойство Clips. Чтобы закодировать только первые шесть секунд видеоролика, используйте примерно такой код:
src.Sources[0].Clips[0].StartTime = new TimeSpan(0);
src.Sources[0].Clips[0].EndTime = new TimeSpan(0, 0, 6);
Для добавления других видеороликов в качестве исходных файлов можно подписать их имена к значению свойства Sources вашего MediaItem. Это приведет к кодированию исходных файлов по порядку в один выходной файл:
MediaItem src = new MediaItem(@"C:\WMdownloads\AdrenalineRush.wmv");
src.Sources.Add(new Source(@"C:\WMdownloads\Video2.wmv"));
Кодирование «на лету»
Expression Encoder также поддерживает кодирование из источников видео реального времени, например веб-камер. Концепция (и код) похожа на применяемую при кодировании видеофайлов, но используется другой набор классов. Они находятся в пространстве имен Microsoft.Expression.Encoder.Live.
Первый класс, который вы должны задействовать, — LiveJob. Он работает подобно Encoder.Job — выполняет работу по кодированию видео. Однако в данном случае OutputFormat — это свойство LiveJob, а не объекта MediaItem (который не нужен). Когда создается экземпляр объекта LiveJob, он ищет устройства ввода видео, подключенные к компьютеру, и заполняет свойства VideoDevices и AudioDevices. После этого вы можете пользоваться ими как входным источником для кодировщика. Пример показан на рис. 4.
Рис. 4. Кодирование видео «на лету»
using (LiveJob job = new LiveJob())
{
LiveDevice videoDevice = job.VideoDevices[0];
LiveDevice audioDevice = job.AudioDevices[0];
LiveDeviceSource liveSource = job.AddDeviceSource(videoDevice,
audioDevice);
job.ActivateSource(liveSource);
WindowsMediaBroadcastOutputFormat outputFormat = new
WindowsMediaBroadcastOutputFormat();
outputFormat.BroadcastPort = 8080;
job.OutputFormat = outputFormat;
Console.WriteLine("Press enter to stop encoding...");
job.StartEncoding();
Console.ReadLine();
Console.WriteLine("Stopping");
job.StopEncoding();
}
Этот код начнет сеанс кодирования «на лету», используя веб-камеру (если она у вас подключена) и транслировать полученное видео на вашей локальной машине через порт 8080. Для просмотра кодируемого потока «в прямом эфире» откройте Windows Media Player и выберите File | Open URL, а затем введите mms://localhost:8080. После буферизации какой-то части видеопотока вы должны увидеть видео, передаваемое веб-камерой, хоть и с лагом в 20–30 секунд из-за времени, уходящего на кодирование и передачу потока данных. Потенциально это видео можно было бы использовать как источник для Windows Media Services или IIS Media Services для широковещательной передачи всему миру.
Дополнительные инструменты
Если вы не уверены, что выбранные вами параметры кодирования дадут нужное качество вывода, воспользуйтесь удобным инструментом в Expression Encoder 3 UI — A/B Compare. Он позволяет кодировать пять секунд видео вокруг текущей позиции воспроизведения. Это видео появится рядом с исходным (рис. 5), и вы сможете легко сравнить качество сжатого видео с оригинальным.
Рис. 5. A/B Compare в Expression Encoder 3
Затем вы можете сохранить текущие параметры как пользовательский пресет, выбрав Edit | Save current settings as preset. Этот пресет будет храниться как XML-файл, который можно использовать с SDK:
job.ApplyPreset(@"C:\WMdownloads\NewPreset.xml");
Если вы уже думаете о том, как легко было бы автоматизировать процесс конвертации видео с помощью консольного приложения, взгляните на Convert-Media PowerShell Module for Expression Encoder, доступный по ссылке convertmedia.codeplex.com. Этот модуль PowerShell обертывает Expression Encoder SDK, предоставляя интерфейс кодирования из командной строки, не требующий написания никакого кода. Как и все проекты CodePlex, этот проект тоже с открытым исходным кодом.
Надеюсь, теперь вы понимаете базовую терминологию, связанную с кодированием видео, и можете принимать обоснованные решения по выбору кодеков и битрейтов. Вы также знаете, как использовать Expression Encoder 3 SDK, чтобы кодировать видеоролики под конкретные платформы вроде Xbox 360, iPhone и Silverlight, а также обрабатывать потоковое видео. Так что не ждите, когда вы окажетесь запертым на чердаке подобно Кларку Гризвулду, чтобы осознать ценность домашнего видеоархива и забытых воспоминаний. Преобразуйте их в формат, который сделает их доступными всему миру.
Адам Миллер (Adam Miller) — инженер ПО в Nebraska Global в Линкольне, штат Небраска. Вы найдете его блог по ссылке blog.milrr.com.
Выражаю благодарность за рецензирование статьи эксперту: Бену Рашу (Ben Rush)