3
votes

I need to stream or download and play an audio getted from an URL in Unity3D, running on iOS. The Audio comes from a text-to-audio service and I need to play it on Unity:

http://api.ispeech.org/api/rest?apikey=...&action=convert&voice=eurspanishfemale&text=hola+que+tal

I've been googling all the morning and not found a valid solution... There is a code snippet in the Unity3D documentation (WWW-audioClip,WWW.GetAudioClip), but is not working, I have debugged and the error says it couldn't open the file.

using UnityEngine;
using System.Collections;

public class AudioURLScript : MonoBehaviour {
    public string url = "http://api.ispeech.org/api/rest?apikey=...&action=convert&voice=eurspanishfemale&text=hola+que+tal";
    public AudioSource source;
    void Start() {
        WWW www = new WWW("file://"+url);
        source = GetComponent<AudioSource>();
        source.clip = www.GetAudioClip(false,true);
    }
    void Update() {
        if (!source.isPlaying && source.clip.isReadyToPlay)
            source.Play();

    }
}

Thanks

SOLUTION

This is my working solution right now.

void Start(){
    StartCoroutine(DownloadAndPlay("http://api.ispeech.org/api/rest?apikey=...&action=convert&voice=eurspanishfemale&text=Hola+que+tal"));  
}

IEnumerator DownloadAndPlay(string url)
{
    WWW www = new WWW(url);
    yield return www;
    AudioSource audio = GetComponent<AudioSource>();
    audio.clip = www.GetAudioClip(false, true,AudioType.MPEG);
    audio.Play();
}
2

2 Answers

2
votes

A WWW object is a wrapper for a HTTP request, containing the creation of the connection, the transfer of the data and the closing of the connection (and some extra actions).

This does not happen in one frame and requires a coroutine.

void Start() {
        StartCoroutine(GetAudio(url));
    }
private IEnumerator GetAudio(string url)
{
    WWW www = new WWW("file://"+url);
    yield return www;
    if(string.IsNullOrEmpty(www.error) == false)
    {
       Debug.Log("Did not work"); 
       yield break;
    }
    source = GetComponent<AudioSource>();
    source.clip = www.GetAudioClip(false,true);
}
2
votes

You don't mention the platform you are on, so I'm going to assume Windows.

Unity Windows runtime only supports WAV or OGG. The link to the audio service file you provided is downloading as a MP2 Audio File (common in broadcasting). Unity will not be able to play that (or MP3).

For reference, Android and iOS platforms do support MP3 (but not MP2).

So, you're first issue is to make sure your audio source is in compatible format.

The code sample is incorrect for 3 reasons;

  1. the URL is https: (which tells unity to download from the internet) but then you pre-pend file: to it (which tells unity to load from the local file system). So you should pick one or the other.
  2. it wouldn't work if you picked https because that particular link (I know it's just an example) but it requires a user to be logged in to the service (and using cookies to know that), so it doesn't send you an audio file, it sends you a HTML page telling the user to login or register.
  3. As @fafase says, the WWW must be placed within a co-routine, so that it can download over multiple frames.

OK, here's what I suggest.

If you can know the audio files a head of time, download them and transcode to OGG (if windows) or MP3 (if mobile) and upload them to your own server (say Amazon S3, or a $10 a month unlimited website).

Then, use this code to download and play it:

StartCoroutine(DownloadAndPlay("http://myserver.com/audio/test.ogg"));  

IEnumerator DownloadAndPlay(string url)
{
    WWW www = new WWW(url);
    yield return www;

    AudioSource audio = GetComponent<AudioSource>();
    audio.clip = www.GetAudioClip(false, false);
    audio.Play();
}