Архив журнала Хакер на www.realsoft.by.ru, номер #058, стр. 058-082-1, Свой видеокомбайн на Delphi

Издательский дом ООО "Гейм Лэнд" ЖУРНАЛ ХАКЕР #58, ОКТЯБРЬ 2003 г.

Свой видеокомбайн на Delphi

Лозовский Александр

Xakep, номер #058, стр. 058-082-1

(alexander@real.xakep.ru)

Пишем проигрыватель AVI-файлов

В августовском Кодинге я рассказывал, как создать собственный подарочный аудиоплеер. Сразу после выхода того номера, мне на почту стали приходить письма в духе: "Звук это круто, но хотелось бы еще и видео. Расскажи, как или кинь линк, где узнать". Требования эти становятся все настойчивее, и мне ничего не остается, кроме как рассказать об этом сразу всем.

Мечта-идея

Компонентов, помогающих нам в проигрывании AVI-файлов (а именно о них сегодня пойдет речь), не так много. Самым достойным из них является произведение наших братьев из Германии под названием: "Multimedia Tools" (www.alcatech.de/download/mmtools/mmtool6.exe, это линк для Delphi 6). Как ни странно, оно оправдывает свое подозрительное название. Дело в том, что разработчики постарались в одном пакете собрать все, что может потребоваться кодеру мультимедийных продуктов на всех этапах производства, от дизайна до работы с аудио/видео файлами. В 2,3 Мб хранятся компоненты для записи, воспроизведения и редактирования (кстати, весьма профессионального) WAV-файлов, визуализации звукового потока, создания, редактирования и воспроизведения AVI-файлов и многое другое. Мне не хватит трех таких статей, чтобы рассказать обо всем пакете, а вот разработчики напряглись и сделали набор примерно из 100 демок, который ты можешь качнуть с www.alcatech.de/download/mmtools/mmdemos.exe. Весят они всего 3,3 Мб. Правда, наличие демок не оправдывает полное отсутствие хелпа или другой вразумительной документации (кроме весьма общего обзора компонентов). Надпись "Currently there are still no helpfiles available, sorry ;-(" висит на их сайте с 1998 года и вряд ли когда-нибудь исчезнет.

Инсталляция

Устанавливается это немецкое чудо по старой схеме: распаковка архива -> открытие файла *.dpk (имя зависит от версии) из каталога с компонентом (кстати, не забудь, что путь к этой директории должен быть прописан в path), далее - ОК -> Compile -> Install.

Это все, теперь самое время посмотреть на палитру компонентов. Там прибавилось целых 8 закладок (MMTools, MMDesign, MMWave, MMVisual, MMMixer, MMDSP, MMDSOUND, MMAVI). Несмотря на то, что нас сегодня интересует в основном содержимое последней вкладки (в ней находятся инструменты для работы с AVI-файлами, в том числе DivX), я опишу и некоторые другие компоненты. Они тебе тоже пригодятся.

Путь к сердцу юзера лежит через интерфейс

Этот факт разработчики знают не хуже нас, поэтому закладки MMTOOLS и MMDESIGN пестрят разными приятными компонентами. Например:

MMWheel - колесико, похожее на то, которым регулируется громкость радиоприемника.

Для этого его и рекомендуют использовать, но, по сути, это - круглая замена трекбару.

Свойства Value, MinValue и MaxValue говорят сами за себя.

MMLEDLABEL - позволяет делать label'ы, имеющие вид "информационного табло" (по типу часов в метро). Такой же вид имеют MMLEDPanel (обычный счетчик) и MMLEDSpin (счетчик + стрелки вверх/вниз для изменения показаний). Также имеются собственные аналоги Gauge, обычного Edit'a, Edit'a для флоат-чисел, красочные CheckBox’ы, RadioButton’ы и многое другое. Хотя все это заточено для управления и визуализации звука, ничто не мешает тебе использовать их в любых других приложениях.

Вперед на стр. 058-082-2


Архив журнала Хакер на www.realsoft.by.ru, номер #058, стр. 058-082-2, Свой видеокомбайн на Delphi

Издательский дом ООО "Гейм Лэнд" ЖУРНАЛ ХАКЕР #58, ОКТЯБРЬ 2003 г.

Свой видеокомбайн на Delphi

Лозовский Александр

Xakep, номер #058, стр. 058-082-2

TMMHiTimer - аналог обычного таймера, но, по утверждению разработчиков, имеющий большую точность. К тому же свойство Priority определяет приоритет его потока. Это может быть очень важно.

Вкладка "Wave"

Здесь содержится гигантское количество компонентов, связанных со звуком - воспроизведение, запись, конвертирование и т.п.

MMWavePlayer - плеер, он и в Африке плеер. Позволяет работать с моно, стерео и мультиканальным звуком. Понимает только один формат - WAV. Старые добрые процедуры Play, Stop и Pause присутствуют и в нем, поэтому пойдем дальше.

TMMWaveRecorder - компонент, предназначенный для записи звука. Очень похож на предыдущий, только работа его инициируется процедурой Recording.

Это, как ты понимаешь, 2 основных компонента, но есть еще куча дополнительных, предназначенных для фильтрации, построения различных кривых и многого другого. В освоении их тебе помогут демы.

Вкладка "Visual"

Компоненты, визуализирующие звуковой поток. Иначе говоря - осциллоскопы, построители спектрограмм, уровни... в общем, это надо видеть. А увидев, сказать: "О, я-я, дас ист гут. Штангентзиркуль! Гут!"

Работа с AVI-файлами (закладка MMAVI)

AVIOpenDialog - стандартный диалог открытия, переделанный под мультимедийные файлы. Из серьезных изменений я заметил только фильтр расширений и немецкий язык интерфейса, поэтому пользоваться им может только настоящий фанат Вольфштайна. Имеется также MMAVISaveDialog как диалог сохранения.

TMMAVIFile - пожалуй, самый важный компонент, предназначенный для обслуживания AVI-файла. Свойство FileName определяет имя файла, AccessMode задает тип доступа (amRead - только чтение, amReadWrite - чтение-запись, amWrite - запись). После этого ты получаешь доступ к самым интимным местам файла (я имею в виду потоки). Осуществить этот самый доступ поможет, например, функция TypedStreams - после передачи ей типа (stVideo/stAudio) и номера потока, она вернет тебе переменную типа TMMAVIStream. Как это использовать, я покажу на примере.

Процедуры:

OpenFile - открывает заданный файл.

CreateFile - создает новый файл (дело в том, что с помощью этой коллекции можно также создавать AVI-файлы).

CreateVideoStream - создает видеопоток в заданном файле (для этого ей надо передать FrameRate (как правило, 1) и имя потока - любую строку). Например: "MainSound". Возвращает переменную типа TMMAVIStream.

CreateAudioStream - соответственно создает аудиопоток (в качестве аргументов - формат и имя потока).

Да, кстати, все нижеописанные компоненты работают только с файлом, обработанным TMMAVIFile, поэтому свойства, типа FileName, у них нет.

MMAVIControl - отменный пульт контроля над воспроизведением аудио и видео. Уже содержит в себе кнопки Play, Stop, Pause, трек для быстрой навигации и таймер. В общем, отличная вещь.

Свойства:

VideoDisplay - определяет имя компонента, показывающего изображение. Обычно это MMAVIVideoDisplay, его я опишу чуть позже.


Архив журнала Хакер на www.realsoft.by.ru, номер #058, стр. 058-082-3, Свой видеокомбайн на Delphi

Издательский дом ООО "Гейм Лэнд" ЖУРНАЛ ХАКЕР #58, ОКТЯБРЬ 2003 г.

Свой видеокомбайн на Delphi

Лозовский Александр

Xakep, номер #058, стр. 058-082-3

RewindWhenDone - если TRUE, то позиция чтения файла по окончании воспроизведения возвращается к началу, если FALSE - остается.

AddFile - добавляет файл в список воспроизведения. Ей необходимо передать имя компонента TMMAVIFile.

AddStream - то же самое, но для потока.

hasAudio - принимает значение TRUE, если в заданном файле присутствует звук.

hasVideo - аналогично предыдущей, но для видео.

Playing - становится TRUE, если идет процесс воспроизведения.

Paused - TRUE, если воспроизведение на паузе.

И, наконец, процедуры PLAY, PAUSE и STOP заботятся, соответственно, о запуске воспроизведения, паузе и стопе.

Зная эти и некоторые другие процедуры, можно легко обойтись без визуальной части этого компонента и сделать собственный дизайн. Точнее, мы просто обязаны это сделать, если твое творение выйдет за пределы твоего компа. Думаю, пользователю не надо знать, почему он заплатил $20 за прогу, написанную с помощью чужих компонентов :). Правда, Multimedia Tools стоят около 260 евро, так что все справедливо.

MMAVIVideoDisplay - компонент-дисплей. Перед началом работы, как я уже говорил, должен быть связан с MMAVIControl, хотя возможна и работа на автопилоте - в этом случае показывать он будет не весь поток, а отдельные фреймы. Для этого необходимо:

1) Добавить файл в список.

2) Передать номер потока (то есть, первый).

3) Выбрать номер фрейма: AVIDisplay.FrameIdx := номер. Нумеруются они от нуля до Streams[x].Length-1, поэтому экранизацией легко управлять с помощью трекбара или слайдера.

MMAVICompressor - отвечает за работу с AVI-файлами. Например, ты легко можешь создать собственную AVI’шку из нескольких BMP, записывать потоки в файл и многое другое. По сути, это - путь к редактированию авишек. А плеер с функциями editor’а - это уже о-го-го, такое даже WMPlayer’у не под силу.

AddStream - добавляет поток в файл. Откуда брать поток и файл? Об этом я уже писал чуть выше, когда рассказывал про TMMAVIFile. Ей передается только один аргумент - переменная типа TMMAVIStream.

SaveToFile - сохраняет потоки в файле; главное здесь - не скинуть на диск ненужные данные, поэтому пользуйся FreeStreams как процедурой, обнуляющей список потоков. Те же действия, проведенные для аудиопотока с сохранением в WAV-файл, позволяют выдирать звук из файла кино. Возьми на заметку - очень полезная вещь.

Кодинг

Наконец-то мы переходим к торжественной части. Она будет совсем несложной, и тебе понадобится не более 1% CPU твоего мозга.

Клади на форму компоненты: 1 MMLabel (объемный лейбл из MMTools), 1 MMAVIVideoDisplay, 1 MMAVIOpenDialog, 1 MMAVIFile, 1 MMAVICompressor, 1 MMSlider (по типу трекбара из MMTools), 1 MMAVISaveDialog, 1 MMAVIControl, 4 кнопки. Вот как это примерно должно выглядеть:

Расставим caption’ы:

Button1 - "открыть...". Это кнопка для открытия файлов.

Button2 - "Обн. фреймы". А эта обнуляет список сохраненных фреймов.

Button3 - "Порвать A/V". Позволяет делить AVI-файл на два - с видео и со звуком.

Button4 - "По кадрам". После ее нажатия ты сможешь выбирать нужный тебе кадр с помощью slider'a.


Архив журнала Хакер на www.realsoft.by.ru, номер #058, стр. 058-082-4, Свой видеокомбайн на Delphi

Издательский дом ООО "Гейм Лэнд" ЖУРНАЛ ХАКЕР #58, ОКТЯБРЬ 2003 г.

Свой видеокомбайн на Delphi

Лозовский Александр

Xakep, номер #058, стр. 058-082-4

Вот что у меня получилось:

Теперь, когда интерфейс более или менее готов, пора бы внести пару строчек кода. Начнем с самого главного - онклика для первой кнопки. Вот он:

IF MMAVIOpenDialog1.Execute then //Если диалог сработал, то

begin

MMAVIFile1.FileName := MMAVIOpenDialog1.FileName; //Передадим имя компоненту

Caption := ExtractFileName(MMAVIOpenDialog1.FileName);

MMAVIFile1.OpenFile;

MMAVIControl1.FreeStreams;

MMAVIControl1.AddFile(MMAVIFile1);

MMAVIVideoDisplay1.Refresh;

end;

Здесь все должно быть понятно, если ты читал теорию, поэтому пойдем дальше - сразу ко второй кнопке, запускающей процесс навигации по кадрам. Посмотрим на OnClick:

MMAVIVideoDisplay1.AddFile(MMAVIFile1); //Ассоциируем MMAVIVideoDisplay1 с //файлом

MMAVIVideoDisplay1.StreamIdx := 0; //Берем первый поток

MMSlider1.MaxValue:= MMAVIFile1.Streams[0].Length-1; //Макс. значение слайдера

MMSlider1.Enabled := True; //Включаем слайдер

После этого подготовительного этапа и создания события OnChange для слайдера:

MMAVIVideoDisplay1.FrameIdx := MMSlider1.Position;

каждое изменение его положения будет нам выводить соответствующий кадр. Сохранить его в файл мы сможем простым кликом на дисплее. Вот и создавай событие MMAVIVideoDisplay1Click и пиши туда содержимое соответствующей врезки:

Логика такая - после клика на компоненте мы создаем растровый файл (т.е. bmp) и копируем туда содержимое MMAVIVideoDisplay1. И поскольку нас интересует чистый кадр без границ компонента, мы их аккуратненько обрезаем. Именно для этого нужны манипуляции с размерами, которые ты видел во врезке.

Имя файла имеет вид picX.bmp, где Х - номер по порядку, от нуля до... сколько изволите :). Для ее инициализации не забудь вдолбить в OnCreate формы и ОнКлик button2:

N:=0;

Разрывной файл

Как я уже говорил, функция деления исходного файла на два (аудио и видео) - это жемчужина любой медиа-проги :), поскольку многие юзеры мечтают сохранять любимые фразы/музон из фильмов. Просто они не знают, как это сделать. А мы с тобой знаем, поэтому и ставим онклик для третьей кнопки:

Принцип работы этого кода тебе ясен, поскольку ты внимательно читал статью, но учти, что файлы эти сохраняются в каталоге С ИСХОДНЫМ ФАЙЛОМ и имеют имена в виде имя_исходного_audio.wav и имя_исходного_video.avi.

Логическое завершение

Этот компонент не единственный, позволяющий легко и непринужденно проигрывать видео. Есть и другой путь, а именно - жестокая эксплуатация Windows Media Player (думаю, для тебя не секрет, что все продукты от MS легко управляются ИЗВНЕ :)). Для упрощения этой и без того несложной задачи, был выпущен компонент TActiveMovie (качай его с www.delphicity.com/amovie/amovie.zip или бери на диске). Он позволяет встраивать Windows Media Player (старше 6.4 версии) в твою форму. Отсюда следуют и его достоинства - он может проигрывать клипы в любом направлении (вперед-назад), увеличивать/уменьшать изображение, захватывать кадры и делать с ними все, что придет в голову. За это приходится расплачиваться интерфейсом WMP на твоей проге. Как ни странно, эта особенность не помешала ему дожить до 5 версии. Разобраться с ним несложно, на сайте есть довольно подробная документация. Естественно, на 100% english language. Да, кстати, помимо MTools у Swift Software есть и другие продукты. Загляни на www.swiftsoft.de/downloads.html. Возможно, тебе понравится что-то еще. На этом все. Удачи!


Архив журнала Хакер на www.realsoft.by.ru, номер #058, стр. 058-082-5, Свой видеокомбайн на Delphi

Издательский дом ООО "Гейм Лэнд" ЖУРНАЛ ХАКЕР #58, ОКТЯБРЬ 2003 г.

Свой видеокомбайн на Delphi

Лозовский Александр

Xakep, номер #058, стр. 058-082-5

procedure TForm1.MMAVIVideoDisplay1Click(Sender: TObject);

var

Bmp: TBitmap; //объявляем растровый файл

begin

MMAVIVideoDisplay1.Refresh; //Освежимся :)

Bmp := TBitmap.Create; //Создаем файл

try //Попытаемся (на случай ошибки)

Bmp.Width := MMAVIVideoDisplay1.Width-2*MMAVIVideoDisplay1.BevelExtend; //ширина битмапа=ширине кадра - границы

Bmp.Height:= MMAVIVideoDisplay1.Height-2*MMAVIVideoDisplay1.BevelExtend; //То же с высотой

Bmp.Canvas.CopyRect(Rect(0,0,Bmp.Width,Bmp.Height), //Копируем соответствующий прямоугольничек

MMAVIVideoDisplay1.Canvas,MMAVIVideoDisplay1.BeveledRect); //в битмап

Bmp.SaveToFile('pic'+inttostr(N)+'.bmp'); //сохраняем файл на диск

Inc(n); //увеличим счетчик

finally

Bmp.Free; //освободим память

end;

end;

procedure TForm1.Button3Click(Sender: TObject);

var

VideoStream: TMMAVIStream; //Аудиопоток

AudioStream: TMMAVIStream; //Видеопоток

FName: string;

begin

VideoStream := MMAVIFile1.TypedStreams[stVideo,0]; //берем первый видеопоток

AudioStream := MMAVIFile1.TypedStreams[stAudio,0]; //То же для аудио

try

FName := ExtractFilePath(MMAVIFile1.FileName)+ChangeFileExt(ExtractFileName(MMAVIFile1.FileName),'');

//Получаем имя файла, выбранного юзером

With MMAVICompressor1 do //Работаем

begin

AddStream(VideoStream); //Добавим

SaveToFile(FName+'_video.avi'); //Сохраняем в файл

FreeStreams; //Освобождаем

AddStream(AudioStream); //Добавим аудио

SaveToFile(FName+'_audio.wav'); //И скинем его на диск

FreeStreams;

end

finally

ShowMessage ('Файл успешно порван на аудио и видео!'); //Поведаем об успехе

end;

end;