Компания
172,31
рейтинг
25 сентября 2014 в 10:20

Разработка → Как мы внедряли INDE в наше Android приложение


Применение готовых библиотек в приложениях освобождает программистов от непроизводительного труда по изобретению велосипедов, сокращает время выхода приложения на рынок и благотворно сказывается на его функциональности. Все эти тезисы мы можем проиллюстрировать на своем собственном примере. В этой статье мы опишем процесс внедрения библиотеки Intel INDE (Integrated Native Developer Experience) для работы с видео в Android в наше существующее приложение Together Video Camera, приведем примеры реализации функционала в соответствии с конкретными нуждами приложения и опишем сложности разработки до и после INDE.


Предыстория

Приложение Together мы начали делать в далеком 2012 году. Проект был в каком-то роде корпоративным хобби, так как большую часть времени мы работали на проектах наших клиентов, разрабатывая различные видео сервисы и приложения. Together задумывался как простой и удобный видео редактор с возможностями по организации видео библиотеки (все видео вместе с удобным доступом). Возможности по редактированию должны были быть максимально простыми, чтобы пользователям, незнакомым с концепциями видео редакторов, было удобно создавать короткометражные фильмы в кратчайшие сроки.

Разработка до внедрения INDE

В то время средств для работы с видео под Андроид практически ничего не было, а для чуть более интеллектуальной обработки видео требовалось погружение в C код. Всю обработку видео мы делали на основе ПО с открытым исходным кодом ffmpeg. Данный подход потребовал значительных инвестиций времени и сил разработчиков. После запуска мы узнали, что наша лаборатория тестовых устройств из дюжины девайсов крайне скудна, от пользователей приходили сотни разнообразных плохо документированных ошибок различных платформ. Развитие собственного клиентского видео SDK отнимало все больше времени от основного продукта, от улучшения User Experience. Надо было что-то делать.

Внедрение INDE

Новость об инструментарии INDE очень сильно нас заинтересовала. Мы случайно услышали о нем на конференции Droidcon 2014. Прежде всего, для нас были важны следующие возможности платформы:
  • Транскодинг видео с различными параметрами
  • Подрезка видео по заданному интервалу
  • Склейка нескольких видео в одно
  • Наложение аудио и видео эффектов

Даже эти несколько пунктов перекрывали с лихвой результаты нашей собственной разработки. С этого момента коренным образом изменился подход к проектированию функциональности нашего приложения. Теперь мы отталкивались не от того, что мы можем дать пользователю, а от того, что бы пользователь хотел.
Нам хватило нескольких дней, чтобы перевести уже существующий функционал на работу с библиотекой INDE. К примеру, для обрезки видеозаписи достаточно добавить сегмент при компоновке MediaComposer-а:

private void setTranscodeParameters(MediaComposer composer) throws IOException
{
	composer.addSourceFile(inputFile);
	composer.setTargetFile(outputFile);
		
	configureVideoEncoder(composer, videoWidthOut, videoHeightOut);
	configureAudioEncoder(composer);
		
	MediaFile mediaFile = mediaComposer.getSourceFiles().get(0);
	mediaFile.addSegment(new Pair<Long, Long>((long)startCutTime, (long)endCutTime));
		
	configureRotateEffect(composer);
}

Чтобы уменьшить видео перед отправкой на сервер, достаточно задать нужные размеры в параметрах MediaComposera перед началом транскодинга. Причем, даже если размеры будут не пропорциональны исходному видео, оно без проблем впишется в заданный прямоугольник:

private void configureVideoEncoder(MediaComposer composer, int outWidth, int outHeight) 
{
	VideoFormatAndroid videoFormat = new VideoFormatAndroid(videoMimeType, outWidth, outHeight);

        videoFormat.setVideoBitRateInKBytes(videoBitRateInKBytes);
        videoFormat.setVideoFrameRate(videoFrameRate);
        videoFormat.setVideoIFrameInterval(videoIFrameInterval);

        mediaComposer.setTargetVideoFormat(videoFormat);
}


Непростая в нашем понимании операция разворота видео с учетом мета-даты источника в терминологии INDE и вовсе значилась всего лишь как видео-эффект.

private void configureRotateEffect(MediaComposer composer) 
{
	if (rotation == 0) return;
		
	IVideoEffect effect = new RotateEffect(rotation, factory.getEglUtil());
	// добавляем эффект на всю длину видео
	effect.setSegment(new Pair<Long, Long>(0L, 0L));
	composer.addVideoEffect(effect);
}


То есть, при желании в процессе транскодинга можно перевернуть только часть видео, так как эффект накладывается на определенный временной отрезок. Сложно представить, где это может пригодиться, но сама возможность почему-то радует.

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

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

Основное предназначение альбомов — это создание видео истории и быстрый шаринг в социальные сети. Так как для этого все равно нужно было бы залить видео в сеть, то еще на ранних этапах разработки было принято решение транскодить альбомы в облаке. Таким образом достигается единообразие процесса транскодинга и экономятся ресурсы девайса пользователя. Но затем мы обнаружили некоторые проблемы:
  • Во-первых, не удавалось добиться плавного воспроизведения альбома на устройстве, пока он еще не был оттранскодирован. Приходилось составлять плейлист из отдельных видео-элементов и воспроизводить их последовательно. Причем каждый элемент требовал соблюдения workflow работы с MediaPlayer. Так, время необходимое на prepare() негативно сказывалось на общем впечатлении от видео, поскольку были заметны небольшие остановки между частями альбома. Кроме того, нужно учитывать, что работа MediaPlayer существенно различается в зависимости от устройства.
  • Во-вторых, пользователям было тяжело подстраивать видеоряд под музыку. Если на устройстве удавалось добиться идеального результата, то на сервере после транскодинга смена элементов плейлиста происходила быстрее и музыка уже не ложилась так, как это задумывалось.
  • В-третьих, было проблемно воспроизводить изображения. Приходилось просто отображать статичную картинку определенной длительности поверх MediaPlayer. Опять же это не соотносилось с финальным видео на сервере после транскодинга, так как там еще добавлялась анимация.

Соответственно, если дополнительно транскодить альбом на устройстве при каждом изменении порядка видео, это решило бы все проблемы, и пользователь смог бы видеть если не абсолютно точный, то очень близкий вариант итогового фильма. Эта возможность бывает особенно полезной, если составление и редактирование альбома полностью происходит в offline, когда просто невозможно зайти на сайт и увидеть результат. Решить подобную задачу при помощи ffmpeg и, главное, добиться одинаково работающего результата на всех устройствах было бы очень тредоемко и затратно по времени. С INDE на это потребовалось не больше одной человеко-недели.

Транскодинг альбомов

Несмотря на то, что процесс инициализации MediaComposer довольно гибкий и простой, в нашем случае потребовались некоторые предварительные действия. В частности, до склеивания альбома необходимо преобразовать все изображения в видео. Для этого по совету разработчиков из INDE мы добавили в приложение 30ти секундный “пустой” видео-файл (80 kb), на который накладывали JpegSubstitudeEffect и обрезали до нужной длительности. Если необходимо не просто статично отображать фотографию несколько секунд, то можно наследовать JpegSubstitudeEffect и преобразовывать координаты фотографии в каждом фрейме так, чтобы получалась некоторая кастомная анимация.

Неприятной неожиданностью стал тот факт, что оказалось невозможно запустить несколько команд проеобразования фото в видео в параллельных потоках одновременно. Существет ограничение на количество одновременных инстансов MediaComposer-a, и для каждого устройства оно свое. К примеру, на устройствах Samsung не удавалось запустить более 3х инстансов. В связи с этим, пришлось преобразовывать изображения последовательно, что довольно продолжительно по времени.

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

@Override
protected void setTranscodeParameters() throws IOException 
{
	String firstPath = playlist.get(0).localPath;
	Uri firstMediaUri = new Uri(firstPath);
		
	mediaComposer.addSourceFile(firstMediaUri);
	mediaComposer.setTargetFile(dstMediaPath);

	configureVideoEncoder(mediaComposer, videoWidthOut, videoHeightOut);
        configureAudioEncoder(mediaComposer);
		
	// add source files in cycle
	Uri nextUri = null;
	for (int i = 1; i < playlist.size(); i++)
	{
		nextUri = new Uri(playlist.get(i).localPath);
		mediaComposer.addSourceFile(nextUri);
	}
}


Чего не удалось добиться

Чтобы полностью повторить на устройстве результат транскодинга альбомов в облаке следовало бы также иметь возможность добавлять саундтрек поверх склеенного видео. В текущей версии библиотеки этого сделать пока не удалось из-за некоторых проблем с SubstituteAudioEffect, которые сейчас активно обсуждаются с разработчиками. Поэтому пока что звуковая дорожка в приложении реализована отдельным плеером, синхронизированным с видео дорожкой по времени.

Как следствие, есть еще один функционал, который мы пока не можем релизовать — это эффект оригинального аудио для некоторых видео в альбоме. Это должно выглядеть следующим образом: несколько видео роликов в альбоме воспроизводятся с наложенным саундтреком и звука самого видео не слышно, а затем саундтрек затихает и становится слышно, к примеру, о чем говорят люди на видео, затем саундтрек снова включается на полную громкость и продолжается воспроизведение. Опять же ждем с нетерпением обновления, чтобы поиграть с этим функционалом.

Производительность

Перед тем как решиться транскодить видео на устройстве перед нами встал основной вопрос: насколько это будет затратно для пользователей по ресурсам. Мы провели несколько тестов на имеющихся устройствах, измеряя время, необходимое на операцию, и затраты батарейки. Результаты приведены ниже.



В итоге, если кратко

Процесс обработки видео на устройстве до и после внедрения INDE отличается как небо и земля. Обычно при переходе с инструментов более низкого уровня на более высокого программист оказывается ограничен теми возможностями, которые ему предоставляет высокоуровневая библиотека. В случае с INDE все совсем не так, напротив, возможностей стало больше и для их реализации требуется существенно меньше времени. Для разработчика остается только самая приятная часть — продумывать архитектуру, улучшать UI и кастомизировать видео или аудио эффекты. Больше никакого погружения в С код, работы с муксерами и демуксерами и неожиданных результатов в зависимости от конкретного устройства.

Конечно остаются некоторые моменты, которые хотелось бы улучшить и исправить, но надо отдать должное разработчикам Intel, они с удовольствием выслушивают такие пожелания и оперативно вносят поправки.

Полезные источники

В статье специально показаны очень короткие примеры, так как на сайте Intel вы можете найти полноценные и понятные исходники. software.intel.com/en-us/articles/intel-inde-media-pack-for-android-tutorials
Автор: @leroid
Intel
рейтинг 172,31

Похожие публикации

Комментарии (1)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка