Блог от AS3Coder'a о JavaScript, HTML, CSS... и немного о Flash.

пятница, 2 декабря 2011 г.

Сохранение звука с микрофона на ActionScript 3.0

То, что недавно казалось фантастикой, сегодня уже реальность. Начиная с версии FlashPlayer'a 10.1 у класса Microphone появилось событие sampleData.

SampleDataEvent

Это событие отправляется когда в буфере микрофона появляются аудио-данные. Событие имеет свойство data, которое содержит образцы записанных с микрофона данных. Естественно данные приходят в сыром формате. И проиграть их вне FlashPlayer'a не получиться. Поэтому их необходимо декодировать, предварительно собрав необходимое количество в бинарный массив ByteArray.

//
// Объявляем бинарный массив для хранения полученных с микрофона аудио-данных
var _samples_arr:ByteArray = new ByteArray();;
//
// Получаем экзмпляр микрофона
var _microphone:Microphone = Microphone.getMicrophone(-1);
//
// Вешаем обработчик события 
_microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, onMicrophoneSampleData, false, 0, true);
//
// Обработчик обновления данных в микрофоне
function onMicrophoneSampleData (e:SampleDataEvent):void
{
  //
  // Добавляем полученные данные в биннарный массив
  _samples_arr.writeBytes(e.data);
}

Для начала выполним преобразование в .wav-формат.

WAVWriter

Специально для этого в Adobe написали класс WAVWriter.as. Останавливаться на нём не будем, потому что он довольно простой в использовании:
//
// Объявляем бинарный массив для данных .wav-файла
var wav_file:ByteArray = new ByteArray();
//
// Объявляем и настроиваем энкондер
var writer:WAVWriter = new WAVWriter();
writer.numOfChannels = 1;
writer.sampleBitRate = 16;
writer.samplingRate = 44100;
//
// Декодируем данные с микрофона в wav-формат
writer.processSamples(wav_file, _samples_arr, 44100, 1);

Теперь, фактически получив бинарные данные аудио-файла в .wav-формате, казалось бы мы выполнили задачу и остается только сохранить их в файл. 

Но мы пойдем дальше. И рассмотрим преобразование наших данных в .mp3-формат. Да, такое уже возможно и реализовано. Говорим спасибо Cyril Diagn за его работу в этом направлении, а именно проект Shine MP3 Encoder on Alchemy.

Shine MP3 Encoder on Alchemy

Это .swc-библиотека с классом ShineMP3Encoder для преобразования данных из .wav-формата в .mp3. Код портирован с помощью Alchemy из энкодера написанного на С, автором которого является Gabriel Bouvigne.

Пример использования:
//
// Обнуляем позицию в массиве .wav-файла
wav_file.position = 0;
//
// Объявляем mp3-энкодер
var _mp3_encoder:ShineMP3Encoder = new ShineMP3Encoder(wav_file);
//
// Вешаем обработчики событий
_mp3_encoder.addEventListener(Event.COMPLETE, onMP3EncoderComplete, false, 0, true);
_mp3_encoder.addEventListener(ProgressEvent.PROGRESS, onMP3EncoderProcess, false, 0, true);
//
// Начинаем кодирование
_mp3_encoder.start();
//
// Обработчик процесса кодирования
function onMP3EncoderProcess (e:ProgressEvent):void
{
  trace("Encoding to mp3 ... " + Math.ceil(e.bytesLoaded * 100 / e.bytesTotal) + "%");
}
//
// Обработчик завершения кодирования
function onMP3EncoderComplete (e:Event):void
{
  trace("Encoding to mp3 complete!")
}

Теперь, после преобразования мы можем сохранить .mp3-файл штатными средствами энкодера. Для этого имеется метод saveAs()
_mp3_encoder.saveAs('record.mp3');

Если же есть необходимость отправить полученный .mp3-файл на сервер, мы можем сделать это самостоятельно, получив его данные во свойстве mp3Data.
var mp3_file:ByteArray = _mp3_encoder.mp3Data;

Ну и как обычно, простейший пример всего вышеописанного:


Ссылки по теме:
       

вторник, 25 октября 2011 г.

Доверенные .swf-файлы

С недавнего времени в контекстном меню FlashPlayer'a появился новый пункт "Глобальные настройки". А именно с версии 10.3.



Если с "Хранилищем", "Камерой и микрофоном" и "Воспроизведением" всё понятно (они итак были доступны в пункте "Параметры..."), то вот во вкладке "Дополнительно" появились доколе неизвестные настройки.

Подробнее я хочу остановить на "Настройках доверенной папки..."



Что за доверенная папка?

На самом деле слово "папки" немного вводит в заблуждение. Естественно здесь указываются .swf-файлы, которым пользователь явно доверяет. А именно:
  • домен, с которого загружаются .swf-файлы,
  • путь к локальному .swf-файлу на компьютере пользователя,
  • путь к локальному каталогу, в котором содержаться .swf-файлы
И что же мы доверяем (разрешаем) указанным файлам?

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

Сделано это для того, чтобы на этапе разработки было не обязательным постоянно выкладывать приложение на сервер.

Для чего указывается домен и что мы ему доверяем, я так и не разобрался. В cправке тоже ничего по поводу доменов. Может разрешаем локальным .swf-файлам загружать данные с этого домена? Не знаю. Не проверял. Может быть вы знаете?


К чему я завел этот разговор?

Недавно пришлось вернуться к одному старому проекту. Проект представляет собой простую презентацию с видео и небольшим каталогом. И вот тут, я столкнулся с тем, что главный .swf-файл зашитый в .exe-файл FlashPlayer'a не может подгрузить данные с каталога, который лежит рядом. Получаю сообщение с ошибкой о нарушении политики безопасности. Удивление конечно было огромным, когда я узнал, что в новых версиях плеера этого делать нельзя.

Чтож? Пришлось разбираться...

Как лечиться?

Ну во-первых, указать доверенный .swf-файл может сам пользователь в соотвествующем окне, о котором я говорил выше.

Во-вторых, можно сделать это за пользователя (естественно с помощью каких-то оберток или стартеров). Для этого в системе (в качестве примера возьму Windows 7, об остальных операционных системах информацию можно найти в справке) имеются каталоги, в которых хранятся .cfg-файлы конфигурации безопасности FlashPlayer'a. Таких каталогов два:

1. Для всех учетных записей системы.

C:\WINDOWS\system32\Macromed\Flash\FlashPlayerTrust

2. Для конкретного пользователя.

C:\Users\JohnD\AppData\Roaming\Macromedia\Flash Player\#Security\FlashPlayerTrust

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

Все современные среды разработки создают свои .cfg-файлы и при создании проекта дописывают в него в качестве доверенной папки папку нового проекта. Именно поэтому многие не заметили этого нововведения. Например FlashDevelop создает вот этот файл:

C:\Users\AS3Coder\AppData\Roaming\Macromedia\Flash Player\#Security\FlashPlayerTrust\FlashDevelop.cfg

А для профилактики подобных ситуаций автор кода может узнать каким образом запущен .swf-файл. Для этого существует свойство Security.sandboxType

Итого

Adobe окончательно уводит FlashPlayer с локального использования в веб. Не пишите больше локальных приложений для него, без оберток, таких как Zinc или AIR.

       

вторник, 25 января 2011 г.

Политика безопасности во Flash Player. Наиболее частные столкновения.

Часто вы сталкивались с ситуацией, когда ваш код не работает по непонятным причинам? Вам кажется, что всё уже проверено сотни раз и вы с уверенностью говорите себе, что здесь нет ошибок, и уже готовы биться головой о клавиатуру :) Спешу вас утешить, скорее всего ошибка не в коде.

В чем же дело?

А дело может быть в том, что вы нарушаете политику безопасности Flash Player, сами того не зная. Иногда Flash Player просто промолчит об этом :)

Как это предупредить?

Если что-то не работает, а по логике должно - идите в справку. Там кроются все ответы на ваши вопросы. Вообще справка должна быть неотъемлемым инструментом разработчика.

В этом посте я хочу рассказать о наиболее частых нарушениях политики безопасности, с которыми мы сталкиваемся.

Загрузка контента с доменов отличных, о того с которого запущена страница с .swf-файлом

*.load();

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

BitmapData.draw();

Метод не отрисует дисплей объект, если в нем есть загруженный контент с другого домена без разрешения. Это касается дочерних элементов класса Loader, и даже TextField, если в нем есть картинки вставленные посредством HTML-разметки.

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

Как получить разрешение?

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

1. checkPolicyFile

Это файл, где перечислены домены, которым разрешено использовать контент. Называться такой файл должен сrossdomain.xml и лежать в корне сайта. Содержимое должно выглядеть следующим образом:

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="
yoursite.com"/>
</cross-domain-policy>

Когда .swf-файл, запущенный с вашего домена, пытается выполнить запросы на другой домен, Flash Player делает автоматически делает запрос на сrossdomain.xml расположенный на другом домене. Если в нем указано разрешение для вашего домена, то Flash Player разрешит в полной мере выполнять запросы.

2. Security.allowDomain() или Security.allowInsecureDomain()

Этот способ предусмотрен для исполняемых .swf-файлов. Если Flash Player встретит в сценарии метод Security.allowDomain() или Security.allowInsecureDomain() (для https-протокола) с параметром равным доменному имени вашего сайта, то он разрешает исполнение сценариев на вашем сайте.

System.allowDomain("yoursite.com");

Взаимодействие с клиентским окружением

Еще одной из частых и самых болезненых, является ситуация когда не выполняются методы никак не связанные с сетью. Болезнь заключается в том, что Flash Player, просто молчит о нарушениях. Приведу список наиболее частых методов, в которых мы сталкиваемся с этим.

FileReference.browse();

Метод не выполнится, если внутри .swf-файла не было события нажатия клавиши мыши.

SharedObject.flush();

Метод не выполнится если размер .swf-файла встроенного на страницу меньше окна с параметрами Flash Player'a (215 x 128).

LocalConnection.send();

Метод не выполнится если вкладка со страницей, на которой запущен .swf-файл, неактивна.

Stage.displayState = StageDisplayState.FULL_SCREEN;

Метод не выполнится, если внутри .swf-файла не было события нажатия мыши.


...

Если вы сталкивались еще с чем-то подобным, пишите в комментарии я дополню этот список.

Доступ к HTML-окружению на странице

.swf-файл загруженный с другого домена (даже с разрешением) не имеет доступ к HTML-окружению на вашей странице. Для этого ему нужно разрешение. Только на этот раз, вы выдаете его сами.

При вставке .swf-файла на страницу необходимо указать параметр AllowScriptAccess с соответствующим параметром:
  • always - Разрешает доступ всем .swf-файлам
  • sameDomain - Разрешает доступ .swf-файлами, загруженным с того же домена, что и страница
  • never - Запрещает доступ всем .swf-файлам
<embed AllowScriptAccess="always" height="100" src="http://www.foreigndomain.com/example.swf" type="application/x-shockwave-flash" width="100"></embed>

Внимание: Учтите, когда вы открываете доступ к HTML-окружению .swf-файлам с неизвестных вам доменов, вы подвергаете всю безопасность на вашей страницы.

Дополнительный материал для изучения

Для более детального ознакомления со всеми правилами безопасности Flash Player, вы можете заглянуть официальную справку на русском языке в раздел "Безопасность проигрывателя Flash Player".

Также смотрите спецификацию по файлу crossdomain.xml
      

Поиск по блогу

Обо мне



Farid Shamsutdinov (AS3Coder)
Russia, Tatarstan, Kazan
as3coder@gmail.com

Подробнее...

Постоянные читатели

© 2014 Farid Shamsutdinov. При копировании материалов, ссылка на источник обязательна. Технологии Blogger.