Forum rules - please read before posting.

Assigning speech audio file from csv

Hello,

Our workflow requires us to name the speech filenames according to our audio files (instead of auto naming)

Is it possible to assign these filenames(with paths) using speech importer?

csv exporter does not export the filenames so wondered if there is a way to do that

thanks

Comments

  • updating my question:

    instead of using speech importer, is it possible to manually gather speech from selected actionlist asset

    this would be my workflow:

    -Assumimg I created an actionlist asset for every dialogue:speech action

    -i will loop through all actionlists in a folder then assign an id to them (something very high so it wont conflict with other gathered text?)

    -then also assign audio file of that speech to be same as the actionlist asset
  • If you don't opt to rely on auto-naming, speech audio files must currently be directly assigned to their associated entry in the Speech Manager.

    If the audio file exists in your project, it is possible to assign it through script. See, for example, the "AssignAudioManually" function in this wiki script, which attempts to automate the switching between auto-naming and manual-assigning modes of existing lines.

    It is possible to export expected audio files when creating script-sheets, but not when importing/exporting game text CSVs. However, this does sound like a useful ability, so I shall give it some thought.

    I'd prefer this workflow over your second, as I don't recommend attempting to gather single ActionLists / text in isolation, as this can cause issues with repeated IDs, mismatching etc. If we focused back on your first, would that be acceptable?

  • thanks!

    one more question.
    I know ac is using assetbundles but not addressables

    would it be easy to implement it?

    where do you load the resources folder?
    and where should I look for the play function of the loaded resource?

    do you think would it be ok if i just load the addressable asset there and play?

    thanks
  • Resources folders are not used if you rely on asset bundles. But when they are used, AC doesn't load up the whole folder - only the file when its needed.

    In both cases, however, the AudioClip needed is provided by the RuntimeLanguages class's GetSpeechAudioClip function. This is virtualised so it's possible to override through subclassing.

  • edited March 2020

    thanks! addressable speech audio works fine

    I switched

    AudioClip clipObj = KickStarter.runtimeLanguages.GetSpeechAudioClip(lineID, speaker);

    with
    AudioClip clipObj = await Addressables.LoadAssetAsync(URL).Task;

    and continued the same process afterwards

    the problem I have is, subtitles does not show up when the audio is found and played. when there is no audio it shows the subtitle. do you have any idea where I messed it up?

    (it shows with the original code, so it's not about subtitle settings)

    I have my subtitles settings on
    unity 2019.3.0f6
    ac 1.70.4

    Thanks

  • Do you have Duplicate for each line? checked in the Menu's properties? Try toggling it.

    If it's checked, the Speech class itself needs to be assigned to the Menu. This is typically handled by the Dialog script's call to AssignSpeechToMenu - but that may not be happening if you've made changes.

    On the topic of addressables: I can confirm that the ability to set custom filenames for speech lines will be a feature of v1.71.0. While I am also looking into potential addressable support, you should at the very least be able to use this custom filename to store the URL - allowing you to override the GetSpeechAudioClip function above, rather than resort to modifying the core Speech class.

  • thanks! going back to dialog script made me realize the speech was returning with empty text as the addressables call is async. so I got the InitSpeech out of the async part and it worked

    same thing for GetSpeechAudioClip function. as the addressable is async I need to await this function and for it I need to have changes in Speech class to have async function right?

    and yes that custom filename will be perfect for us. I was planning on using the description field for that

  • Indeed - the async nature of addressables does make it a little more difficult.

    This would likely be best done by hooking into the custom event system, whereby playing a new speech line triggers the OnStartSpeech event. If you uncheck Auto-play speech audio files? in the Speech Manager, then you can rely solely on custom scripting to handle audio playback.

    Something like this:

    private AudioSource audioSource;
    
    private void OnEnable ()
    {
        EventManager.OnStartSpeech += OnStartSpeech;
        KickStarter.speechManager.searchAudioFiles = false;
    }
    
    private void OnDisable ()
    {
        EventManager.OnStartSpeech -= OnStartSpeech;
    }
    
    private void OnStartSpeech (Char speaker, string text, int lineID)
    {
        audioSource = (speaker != null) ? speaker.speechAudioSource : KickStarter.dialog.GetNarratorAudioSource ();
    
        SpeechLine speechLine = KickStarter.speechManager.GetLine (lineID);
        string filename = speechLine.description; // or GetFilename ();
    
        Addressables.LoadAssetAsync<AudioClip> (filename).Completed += OnCompleteLoad;
    }
    
    private void OnCompleteLoad (AsyncOperationHandle<AudioClip> obj)
    {
        if (obj.Result == null) return;
        audioSource.clip = obj.Result;
        audioSource.loop = false;
        audioSource.Play ();
    }
    
  • oh thank you that is very elegant
  • Hello again Chris,

    so this solution plays the speech from addressables, further testing;

    1)is it possible to delay the subtitles until the audio load? as it loads the audio after the subtitle it has a small delay for the audio play. If not I would delay all subtitles for 50ms or something that might do it

    2) as we disconnected the subtitle and audio, can we pass the subtitle once the audio is over? or for shorter lines keep the subtitle until the audio is over?

  • edited April 2020

    for the subtitle - audio sync:

    this is how I set it currently, can you evaluate if this is the right way?

    -I turned on display subtitles forever under skip
    -I added an unloadclip when the audio is complete, and skipping the subtitle there

        private void OnCompleteLoad(AsyncOperationHandle<AudioClip> obj)
        {
            if (obj.Result == null) return;
    
            audioSource.clip = obj.Result;
            audioSource.loop = false;
    
            UnloadClip(obj);
    
            audioSource.Play();
        }
    
        async Task UnloadClip(AsyncOperationHandle<AudioClip> obj)
        {
            SpeechLine unloadingSpeechLine = currentSpeechLine;
    
            int clipLength = (int)(obj.Result.length * 1000);
            await Task.Delay(clipLength + 100);
    
            Addressables.ReleaseInstance(obj);
    
            //only skip the dialogue if we are still on the same speechline after waiting for the audio duration
            if(unloadingSpeechLine == currentSpeechLine)
            {
                KickStarter.dialog.KillDialog(false, false);
            }
        }
    
  • If audio is played in the normal way (i.e. the Speech class determines the AudioClip internally when constructed), then AC has functionality to end the speech line when the audio ends.

    The Dialog's KillDialog function has an alternative that takes an instance of the Speech class. A reference to the Speech class can be gotten with an alternative to the OnStartSpeech event:

    private void OnEnable () { EventManager.OnStartSpeech_Alt += OnStartSpeech; }
    private void OnDisable () { EventManager.OnStartSpeech_Alt -= OnStartSpeech; }
    private void OnStartSpeech (Speech speech) {}
    

    Regarding the delaying of speech display, you could feasibly turn on your Subtitles menu manually via script, by setting it's Appear type to Manual, and then calling e.g.:

    Menu subtitlesMenu = PlayerMenus.GetMenuWithName ("Subtitles");
    subtitlesMenu.speech = mySpeech;
    subtitlesMenu.TurnOn ();
    

    However, I'll see if it's possible to have a separate Speech constructor class that takes an AudioClip as an override parameter. That way, it would be possible (through, e.g. a subclass of ActionSpeech) to only trigger the speech once you've preloaded the audio.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.