Воспроизведение MP3 с помощью Media с phonegap/Cordova

Моя проблема:

Я использую Media Class от Cordova. Файл MP3 воспроизводится только один раз (в первый раз).

Код:

Добавьте этот код в проект Cordova Starter, чтобы воспроизвести мою проблему:

    var playCounter = 0;
    function playMP3(){
      console.log("playMP3() counter " + playCounter);
      var my_media = new Media("app/www/test.mp3");//ressource buildAction == content
      my_media.play();
      playCounter++;
    }
    [...]
    <p onclick="playMP3();">Click to Play MP3</p>

Вывод VS:

[...]
GapBrowser_Navigated :: /app/www/index.html
'UI Task' (Managed): Loaded 'System.ServiceModel.Web.dll'
'UI Task' (Managed): Loaded 'System.ServiceModel.dll'
Log:"onDeviceReady. You should see this message in Visual Studio's output window."
'UI Task' (Managed): Loaded 'Microsoft.Xna.Framework.dll'
Log:"playMP3() counter 0"
'UI Task' (Managed): Loaded 'System.SR.dll'
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 1}"
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 2}"
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 2, \"value\": 2.141}"
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 4}"
Log:"playMP3() counter 1"
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IsolatedStorage.IsolatedStorageException' occurred in mscorlib.dll
Log:"media on status :: {\"id\": \"2de3388c-bbb6-d896-9e27-660f1402bc2a\", \"msg\": 9, \"value\": 5}"

Моя конфигурация:

  • кордова-1.6.1.js
  • Люмия 800
  • WP 7.5 (7.10.7740.16)

Обходной путь (своего рода):

  • Деактивировать приложение (выключить экран)
  • повторно активировать приложение (включить экран)
  • -> вы получите еще один выстрел.

Любая помощь приветствуется, так как я заблокирован на этом с майских дней, и я нигде не нашел полезной информации.

Кроме того, можете ли вы сказать мне, работает ли этот код в вашей конфигурации?

.

.

.

Обновление: добавлен демо-код, Cordova 1.8.0rc1

используя глобальную переменную. Поддержание экземпляра в живых.

результат

  • Test2.mp3 воспроизводится и может воспроизводиться нормально.
  • test.mp3 вообще не проигрывается.
  • Это первый файл, который вы воспроизводите, который будет работать.

Код

  function onDeviceReady()
  {
  document.getElementById("welcomeMsg").innerHTML += "Cordova is ready! version=" + window.device.cordova;
  console.log("onDeviceReady. You should see this message in Visual Studio's output window.");
  my_media = new Media("app/www/test.mp3");//ressource buildAction == content
  my_media2 = new Media("app/www/test2.mp3");//ressource buildAction == content
  }

  var playCounter = 0;
  var my_media = null;
  function playMP3(){
    console.log("playMP3() counter " + playCounter);
    my_media.play();
    playCounter++;
  }

  var my_media2 = null;
  function playMP32(){
    console.log("playMP32() counter " + playCounter);
    my_media2.play();
    playCounter++;
  }

</script>
[...]

<p onclick="playMP3();">Click to Play MP3</p>
<p onclick="playMP32();">Click to Play MP3 2</p>

Вывод VS:

Log:"onDeviceReady. You should see this message in Visual Studio's output window."
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b
Log:"playMP32() counter 0"
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b
Log:"playMP32() counter 1"
Log:"playMP3() counter 2"
INFO: startPlayingAudio could not find mediaPlayer for b60fa266-d105-a295-a5be-fa2c6b824bc1
A first chance exception of type 'System.ArgumentException' occurred in System.Windows.dll
Error: El parámetro es incorrecto. 
Log:"playMP32() counter 3"
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b

.

.

.

Обновление: Кордова 2.0.0

Я обновил отчет об ошибке Apache с тестовым примером для 2.0.0.

Кто-нибудь может воспроизвести это?

ссылка на отчет об ошибке: https://issues.apache.org/jira/browse/CB- 941


person Loda    schedule 03.06.2012    source источник
comment
Пробовал с последней версией (1.8 rc1) с GitHub. Та же проблема.   -  person Loda    schedule 04.06.2012
comment
примечание: проблема такая же и с 1.8, но ошибки другие.   -  person Loda    schedule 20.06.2012
comment
Если вам небезразлична проблема, я сообщил об этом Apache: issues.apache.org/jira /browse/CB-941   -  person Loda    schedule 20.06.2012


Ответы (5)


Я вижу, что вы получаете исключение IsolatedStorageException при втором щелчке, что заставляет меня думать, что файл удерживается открытым первым экземпляром Media, что предотвращает повторный доступ к нему.

Я предлагаю убедиться, что вы либо создаете только один экземпляр Media для каждого файла, либо сначала смотрите, есть ли способ избавиться от старого экземпляра.

Вот что я бы попробовал (но я не проверял):

 var playCounter = 0;

 // moved my_media here so it won't be recreated
 var my_media = new Media("app/www/test.mp3");//ressource buildAction == content

    function playMP3(){
      console.log("playMP3() counter " + playCounter);
      my_media.play();
      playCounter++;
    }
    [...]
    <p onclick="playMP3();">Click to Play MP3</p>
person Austin Thompson    schedule 19.06.2012
comment
Не работает с 1.6.1. Работайте с 1.8.0rc1, если вы воспроизводите только ОДИН файл. (Вы не можете загрузить другой файл с другим экземпляром MEDIA). Журнал: первое случайное исключение типа «System.ArgumentException» произошло в System.Windows.dll; Ошибка: неверный параметр. - person Loda; 20.06.2012
comment
Но можете ли вы нажать кнопку несколько раз, чтобы воспроизвести один звук в соответствии с вопросом? Воспроизведение нескольких разных звуков немного усложняет задачу, поскольку вы говорите, что не можете одновременно иметь несколько экземпляров Media. В начале каждой кнопки воспроизведения вам нужно будет проверить, имеет ли my_media значение null, остановить и, возможно, отпустить (как сказал @Onur_TOPAL), если оно не равно нулю, а затем создать новый экземпляр. Во всяком случае, это мое предположение. - person Austin Thompson; 20.06.2012
comment
давайте уточним: будет работать только первый файл для воспроизведения (если вы сохраните экземпляр живым, вы можете воспроизводить его несколько раз). Если вы попытаетесь воспроизвести другой файл (создав новый экземпляр MEDIA), это не сработает. .release() .stop() не решают проблему. - person Loda; 20.06.2012
comment
Возможно, вы захотите создать новый вопрос или изменить этот, чтобы отразить, что вы хотите воспроизвести несколько разных звуков. - person Austin Thompson; 20.06.2012
comment
Вопрос про один мп3 так как это самый простой случай воспроизводящий ошибку. Очевидно, в моем приложении есть более одного mp3, и я хочу воспроизвести их более одного раза. Может быть, я не понимаю, я НЕ играю в них одновременно (микшер), а друг за другом (по нажатию кнопки). - person Loda; 21.06.2012
comment
даже вопрос остается открытым, я дал вам награду. Не могли бы вы попытаться воспроизвести проблему в своем конфиге? - person Loda; 21.06.2012

чуть не забыл... это работает для моих целей. Надеюсь, поможет ;-)

WP7.5/Кордова 1.9.0

ТРЕБОВАНИЕ: Насколько мне известно, работает только с файлами .wav. Мне пришлось преобразовать мои файлы .mp3, так как они вызывают уродливые исключения.

ПЛАГИН:С#:

namespace Cordova.Extension.Commands
{
    public class PGSoundFX : BaseCommand
    {
        public Dictionary <string, SoundEffect> fxSoundMap = new Dictionary<string,SoundEffect>();

    public enum FXType
    {
        Load=0,
        Play=1
    }

    [DataContract]
    public class FXOption
    {
        [DataMember]
        public string audioSrc;
        [DataMember]
        public string audioRef;
        [DataMember]
        public FXType fxType; 
    }

    public void groAudio(string options)
    {
        FrameworkDispatcher.Update(); 
        FXOption opts;

        opts = WP7CordovaClassLib.Cordova.JSON.JsonHelper.Deserialize<FXOption>(options);

        if (opts != null)
        {
            try
            {
                switch (opts.fxType)
                {
                    case FXType.Load:
                        loadSound(opts.audioSrc, opts.audioRef);
                        break;
                    case FXType.Play:
                        Dictionary<string, SoundEffect>.KeyCollection keyCol = fxSoundMap.Keys;
                        foreach (string tmp in keyCol)
                        {
                            if ((opts.audioRef).Equals(tmp))
                                playSound(fxSoundMap[tmp]);
                        }
                        break;
                }
            }
            catch
            {
                Debug.WriteLine("PGSoundFX: loadSound Error ... null parameter(s).");
            }
        }
    }

    /// <summary> 
    /// Loads a wav file into an XNA Framework SoundEffect. 
    /// </summary> 
    /// <param name="Sound">The SoundEffect to play.</param> 
    private void playSound(SoundEffect Sound)
    {
        Sound.Play();
        DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
    }

    /// <summary> 
    /// Loads a wav file into an XNA Framework SoundEffect. 
    /// </summary> 
    /// <param name="SoundFilePath">Relative path to the wav file.</param> 
    /// <param name="Sound">The SoundEffect to load the audio into.</param> 
    private void loadSound(String SoundFilePath, String SoundName)
    {
        if (fxSoundMap.Keys != null)
        {
            Dictionary<string, SoundEffect>.KeyCollection keyColl = fxSoundMap.Keys;
            foreach (string tmp in keyColl)
            {
                if (SoundName.Equals(tmp))
                    return;
            }
        }

        SoundEffect Sound = null;

        try
        {
            // Holds informations about a file stream. 
            StreamResourceInfo SoundFileInfo = Application.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
            // Create the SoundEffect from the Stream 
            Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
            fxSoundMap[SoundName] = Sound;
            DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
        }
        catch (NullReferenceException)
        {
            Debug.WriteLine("Couldn't load sound " + SoundFilePath);
        }
        } 
    }
}

Javascript: Плагин:

PhoneGap.addConstructor(function() {

navigator.plugins.pgSoundFX = 
{
    playSound:function(fxName)
    {
    var options = {"audioRef":fxName,"fxType":1};
    PhoneGap.exec(null, null, "PGSoundFX", "groAudio", options);
    },

    loadSound:function(fxSrc, fxName)
    {
    var options = {"audioSrc":fxSrc,"audioRef":fxName,"fxType":0};
    PhoneGap.exec(null, null, "PGSoundFX", "groAudio", options);
    }
}
});

Javascript:Использование:

//NOTE: Allows you to pre-load sound effect files

//initialize pgSoundFX plugin
if (!navigator.plugins) {
    console.log("plugIns do not exist!");
    navigator.plugins = {};
}

navigator.plugins.pgSoundFX.loadSound("www/audio/file1.wav", "item1");
navigator.plugins.pgSoundFX.loadSound("www/audio/file2.wav", "item2");
navigator.plugins.pgSoundFX.loadSound("www/audio/file3.wav", "item3");
    :
    :

//NOTE: Play whenever needed
navigator.plugins.pgSoundFX.playSound("item1");

Конечно, местоположение вашего файла (www/audio/), имена (file1 и т. д.) и имена ссылок (item1 и т. д.) — все, что вы хотите. Как и в большинстве случаев, существует множество способов улучшить этот код... не стесняйтесь. Мой вариант использования предварительно загружает пять файлов .wav размером от 28 КБ до 364 КБ и воспроизводит их на протяжении всей игры пользователя.

person gregg    schedule 06.07.2012

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

сначала создайте свой звук с помощью var my_media = new Media(src, onSuccess, onError); ctor и в случае успеха просто воспроизведите его, а в случае ошибки сначала попробуйте выпустить его с помощью кода media.release.

Ну, если вы знаете какое-то другое событие или действие, чтобы выпустить его, это было бы более уместно.

Редактировать: я только что заметил, что вы не используете stop для мультимедиа, вы также можете попробовать использовать его, когда это необходимо, например, в начале playMP3(), если медиа не равно нулю, попробуйте сначала остановить его.

Ваше здоровье.

person Onur Topal    schedule 20.06.2012
comment
спасибо за вклад. Я пытался вызвать .stop . release и = null перед воссозданием объекта: безуспешно. - person Loda; 20.06.2012
comment
если ваш код все еще такой же, как в вашем вопросе (я имею в виду, что медиа-переменная является локальной), эти функции не будут работать. Вы должны определить его как глобальный, как ответ Остина. Если он все еще не работает даже как глобальная переменная, то я понятия не имею. - person Onur Topal; 22.06.2012

Я думаю, что проблема может быть связана с тем ограничением, что Silverlight допускает только один экземпляр мультимедиа на страницу... и, поскольку PG/Cordova, по сути, является одностраничным экземпляром веб-браузера, он может иметь только один экземпляр мультимедиа. Я играю с созданием плагина XNA SoundEffect, чтобы обойти эту проблему.

person gregg    schedule 22.06.2012
comment
Спасибо за ответ. не забудьте опубликовать ссылку на проект, когда вы его опубликуете. - person Loda; 27.06.2012

была ошибка Cordova https://issues.apache.org/jira/browse/CB-941

решает purpulecabbage в своем репозитории на gitHub. см. комментарий к отчету об ошибке.

person Loda    schedule 28.09.2012
comment
обновление: начиная с 2.1 файл воспроизводится, но реализация обратного вызова глючит. см. отчет об ошибке: issues.apache.org/jira/browse/CB-1593 - person Loda; 14.10.2012
comment
Обновление: ошибка исправлена ​​и объединена. - person Loda; 25.06.2013