Search code examples
pythonpython-3.xpygametext-to-speechgtts

ValueError: mmap closed or invalid


I get the error

ValueError: mmap closed or invalid

Whenever i try and play audio. the code that seems to be the error is

def speak(audioString):
    print(audioString)
    tts = gTTS(text=audioString, lang='en')
    tts.save("audio.mp3")
    with open("audio.mp3") as f: 
        m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 

        pygame.mixer.music.load(m) 
        pygame.mixer.music.play() 

m.close()

I would like help as i was trying to do textToSpeach and am unable to.

edit: put code spaces in right place


Solution

  • This is because you're closing the mmap m as the sound is playing.

    def speak(audioString):
        print(audioString)
        tts = gTTS(text=audioString, lang='en')
        tts.save("audio.mp3")
        with open("audio.mp3") as f: 
            m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 
    
            pygame.mixer.music.load(m) 
            pygame.mixer.music.play() 
    
            # wait for audio to finish playing
            while ( pygame.mixer.music.get_busy() ):
                pygame.event.pump()                    # <-- a bit dodgey
    
            m.close()
    

    A quick test is that commenting out the m.close() makes it work OK. You will need to program some other way of handling the loading/playing. Do you really need the speed optimisation of mmap ?

    Another approach might be to use the io module StringIO and never write the audio stream back to disk:

    Theoretically something like:

    import io
    
    ...
    
    memfile = io.StringIO()
    tts.write_to_fp( memfile )
    pygame.mixer.music.load( memfile )   # <<-- NOTE: untested
    pygame.mixer.music.play()
    # wait for audio to finish playing
    while ( pygame.mixer.music.get_busy() ):
        do_something_useful_and_handle_events()
    memfile = None
    

    But you still probably can't delete memfile while the audio is playing.