Клeвые сайты, приложения, web-сервисы highload-класса
+7 495 215-22-19 Есть вопрос?
Практический курс: Управление digital-проектами
Кейсы
Смотреть все
  • Креатив и анимация
  • Фишки для ecommerce
  • Интеграция с ERP
  • Highload и стартапы
  • Корпоративный сегмент
Смотреть все
Студия
Смотреть все
  • Философия
  • История
  • Команда
  • Награды и достижения
  • Клиенты
  • Отзывы
  • Виски-брейк
  • Работа и стажировка
Смотреть все
Что делаем
Смотреть все
  • Highload
  • E-commerce
  • Приложения
  • Бизнес-сайты
  • Сервис
  • Стартапы
  • Интерфейсы
Смотреть все
Процесс
Смотреть все
  • Аналитика
  • Креатив
  • Разработка и технологии
  • Интеграция
  • Развитие проекта
  • Цены
Смотреть все
Продукты
Смотреть все
  • Scrumban
  • CRM для Scrumban
  • Хуижин
  • Planning poker
  • HelpDesk
Смотреть все
Журнал 9+
Смотреть все
  • Шибко умные мысли
  • Вести с фронта
  • Кейсы
  • Видео
  • Ланч-тайм
  • Хэндбук заказчика
Смотреть все
Контакты
Смотреть все
Смотреть все
Начать проект
+7 495 215-22-19
105005, Москва, ул. Бауманская, 7
БЦ Central Yard, офис 215
info@sibirix.ru, sibirix
Все контакты
© 2003-2018 Сибирикс
SPYK agile marketing group
Комментарии
Назад в журнал
В Декабре прошлого года мы делали небольшое промо-приложение для Facebook, для крупного бренда — производителя мышек и видеокамер. (Ура, после этой фразы аудитория поредела в двое, а пара человек насторожилось). Одной из фич приложения была функция записи голоса с микрофона пользователя. Причем голос накладывался на аудиотрек. Микширование цифрового звука во Flash
Микширование цифрового звука во Flash
В Декабре прошлого года мы делали небольшое промо-приложение для Facebook, для крупного бренда — производителя мышек и видеокамер. (Ура, после этой фразы аудитория поредела в двое, а пара человек насторожилось). Одной из фич приложения была функция записи голоса с микрофона пользователя. Причем голос накладывался на аудиотрек.
Владимир Завертайлов
Владимир Завертайлов
Фото с сайта: www.thepodcasthost.com

Для решения этой задачи мы использовали потоковый сервер Red5 (после некоторых тестов перешли на Wowza). На стороне клиента, естественно, Flash. Передавать на сервер смешанный голос и аудиотрек — технически невозможно (в RTMP-поток может писать только камера и микрофон, но не звук из колонок). Голос пользователя сохранялся потоковым сервером в виде отдельного файла. После чего специально обученный серверный скрипт микшировал голос и аудиотрек, работая через FFmpeg.

Все бы прекрасно, если бы не сетевые задержки. Небольшие, крохотные задержки при старте записи, передаче данных, завершении записи приводили к тому, что музыка и слова шли несинхронно. Задержки составляли от 0.1 до 0.5 секунды, но были всегда произвольными и могли возникать не только в момент старта записи, но и в какие-то моменты посередине. Простым сдвигом/растяжением файла проблема не лечилась. Как оказалось, несинхронный текст и мелодия начинают нервировать уже при задержках в 0.2 сек.

Epic Fail. Итак, задача: Смикшировать аудиопоток с микрофона и проигрываемый файл.

Решение, как водится, под катом.

Всякий, кто решает проблему микширования аудиопотоков в реальном времени, рано или поздно набредает на вот эту неопимистичную заметку. Краткий пересказ: «Ищите дальше!».

Однако! В Flash-плеере 10.1 появилась возможность получать поток данных непосредственно с микрофона (объекта Microphone), в виде массива байт (ByteArray). Вот как это выглядит изнутри:

package { import flash.display.MovieClip; import flash.events.*; import flash.media.*; import flash.utils.Timer; import flash.utils.ByteArray; import flash.net.URLRequest; public class testClass extends MovieClip { const DELAY_LENGTH:int = 10000; var sound:Sound = new Sound(); var channel:SoundChannel = new SoundChannel(); var mic:Microphone; var timer:Timer; var soundBytes:ByteArray = new ByteArray(); var extSound:Sound; var extChannel:SoundChannel; var isMicReady, isSoundReady; public function testClass() { trace("record"); isMicReady = false; isSoundReady = false; var url:String = "1.mp3"; var urlRequest:URLRequest = new URLRequest(url); extSound = new Sound(); extSound.load(urlRequest); extSound.addEventListener(Event.COMPLETE, soundLoaded); mic = Microphone.getMicrophone(); mic.setSilenceLevel(0, DELAY_LENGTH); mic.gain = 100; mic.rate = 44; mic.addEventListener(StatusEvent.STATUS, micStatus); mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); } function micStatus(evt:StatusEvent) { if (evt.code == "Microphone.Unmuted") { isMicReady = true; tryToStart(null); } } function soundLoaded(evt) { isSoundReady = true; tryToStart(null); } function tryToStart(evt) { if (isMicReady && isSoundReady) { startAll(); } } function startAll() { extChannel = extSound.play(); timer = new Timer(DELAY_LENGTH); timer.addEventListener(TimerEvent.TIMER, timerHandler); timer.start(); } function micSampleDataHandler(event:SampleDataEvent):void { //trace(event); if (event.data != null) { while(event.data.bytesAvailable) { var sample:Number = event.data.readFloat(); //event.data.writeFloat(sample - 0.5); soundBytes.writeFloat(sample); } } } function timerHandler(event:TimerEvent):void { trace(soundBytes.length); //extSound.close(); extChannel.stop(); extSound.play(0); mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); timer.stop(); soundBytes.position = 0; sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler); channel.addEventListener( Event.SOUND_COMPLETE, playbackComplete ); channel = sound.play(); } function playbackSampleHandler(event:SampleDataEvent):void { for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++) { //trace(sample); var sample:Number = soundBytes.readFloat(); event.data.writeFloat(sample); event.data.writeFloat(sample); } } function playbackComplete( event:Event ):void { trace( "Playback finished."); } } } 

Добавляем к этому массиву байт заголовки, и получается обычный Wav-файл. А вот MicRecorder и маленькая, прекрасная библиотека, которая проделывает за нас всю эту работу.

Для проигрываения wav-файлов можно так же воспользоваться небольшой библиотекой AS3WavSound.

Таким образом всё микширование цифрового звука (по ссылке — чуть-чуть математики) можно производить на клиенте, передавая на сервер готовый wav-файл. (Впрочем, знатоки матана и рядов Фурье могут отправлять и чего-нибудь покомпактнее :-)).

Комментарии 0
6 февраля 2013
Сегодня первый день маленькой катастрофы: изменение API Facebook
Два дня назад нам начали прилетать уведомления на фейсбуке о том, что они меняют API и некоторые приложения скоро поломаются.
26 июня 2012
Вы решили делать игру ВКонтакте: с чего начать?
Почему вам хочется запустить собственную игру в социальной сети? 
23 января 2012
Lucky Balloons — проверяем свою удачу и срубаем подарки
Эй, амиго! Кто в детстве не мечтал сделать свою игру? Ты не мечтал? А ну, быстро заканчивай читать этот пост!
16 ноября 2011
Грубый, неэтичный, одноразовый метод повышения продаж
Предлагаю немного расслабиться и решить несложную задачку: 
  • Кейсы
  • Что делаем
  • Процесс
  • Философия
  • Журнал 9+
  • Контакты