Picovoice / porcupine

On-device wake word detection powered by deep learning
https://picovoice.ai/
Apache License 2.0
3.76k stars 499 forks source link

Porcupine Issue: PICOVOICE_STATUS_TO_EXCEPTION 00000136 #1266

Closed EA914 closed 6 months ago

EA914 commented 6 months ago

Have you checked the docs and existing issues?

SDK

Python

Porcupine package version

3.0.2

Framework version

Pythonh 3.11

Platform

Raspberry Pi

OS/Browser version

Deboam GNU/Linux 12 (bookworm)

Describe the bug

This is an output of the exact error when I try to run my code.

Traceback (most recent call last):
  File "/home/evan/Documents/Python/Gemini Images/inky041924.py", line 113, in <module>
    main()
  File "/home/evan/Documents/Python/Gemini Images/inky041924.py", line 105, in main
    wait_for_wake_word(picovoice_api_key)
  File "/home/evan/Documents/Python/Gemini Images/inky041924.py", line 18, in wait_for_wake_word
    porcupine = pvporcupine.create(access_key=pico_key, keywords=["Art-Frame"])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/evan/Documents/Python/Gemini Images/myenv/lib/python3.11/site-packages/pvporcupine/_factory.py", line 69, in create
    return Porcupine(
           ^^^^^^^^^^
  File "/home/evan/Documents/Python/Gemini Images/myenv/lib/python3.11/site-packages/pvporcupine/_porcupine.py", line 198, in __init__
    raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](
pvporcupine._porcupine.PorcupineActivationRefusedError: Initialization failed:
  [0] Picovoice Error (code `00000136`)
  [1] Picovoice Error (code `00000136`)
  [2] Picovoice Error (code `00000136`)

The code equivalent (where I am not outputting the image it displays to the inky display, but instead running this on Windows and opening the image it generates in the windows file viewer, works perfectly. This bug seems to be specific to Raspberry Pi OS

Steps To Reproduce

I created a test script to run my code in windows, which works:

import pvporcupine
import pyaudio
import struct

def main():
    # Configuration parameters
    access_key = "ACCESS_KEY_HERE"
    keyword_path = r"C:\Users\Evan Alexander\AppData\Local\Programs\Python\Python312\Lib\site-packages\pvporcupine\resources\keyword_files\windows\Art-Frame_en_windows_v3_0_0.ppn"

    try:
        # Create a Porcupine object with the given access key and keyword file
        porcupine = pvporcupine.create(access_key=access_key, keyword_paths=[keyword_path])

        # Set up audio input stream
        pa = pyaudio.PyAudio()
        audio_stream = pa.open(
            rate=porcupine.sample_rate,
            channels=1,
            format=pyaudio.paInt16,
            input=True,
            frames_per_buffer=porcupine.frame_length
        )

        print("Listening for the wake word 'Art-Frame'...")

        # Main loop to process audio frames
        while True:
            # Read frame from audio input stream
            pcm_frame = audio_stream.read(porcupine.frame_length)
            pcm_frame = struct.unpack_from("h" * porcupine.frame_length, pcm_frame)

            # Process frame to detect keyword
            result = porcupine.process(pcm_frame)
            if result >= 0:
                print("Wake word 'Art-Frame' detected!")

    except KeyboardInterrupt:
        print("Exiting...")
    finally:
        # Clean up resources
        if porcupine is not None:
            porcupine.delete()
        if audio_stream is not None:
            audio_stream.close()
        if pa is not None:
            pa.terminate()

if __name__ == '__main__':
    main()

The equivalent code in linux returns the error:

import pvporcupine
import pyaudio
import struct

def main():
    # Configuration parameters
    access_key = "ACCESS_KEY_HERE" 
    keyword_path = "/home/evan/.local/lib/python3.11/site-packages/pvporcupine/resources/keyword_files/raspberry-pi/Art-Frame_raspberry-pi.ppn"
    # Adjust the path to the location where you have saved the keyword file on your Raspberry Pi

    try:
        # Create a Porcupine object with the given access key and keyword file
        porcupine = pvporcupine.create(access_key=access_key, keyword_paths=[keyword_path])

        # Set up audio input stream
        pa = pyaudio.PyAudio()
        audio_stream = pa.open(
            rate=porcupine.sample_rate,
            channels=1,
            format=pyaudio.paInt16,
            input=True,
            frames_per_buffer=porcupine.frame_length
        )

        print("Listening for the wake word 'Art-Frame'...")

        # Main loop to process audio frames
        while True:
            # Read frame from audio input stream
            pcm_frame = audio_stream.read(porcupine.frame_length)
            pcm_frame = struct.unpack_from("h" * porcupine.frame_length, pcm_frame)

            # Process frame to detect keyword
            result = porcupine.process(pcm_frame)
            if result >= 0:
                print("Wake word 'Art-Frame' detected!")

    except KeyboardInterrupt:
        print("Exiting...")
    finally:
        # Clean up resources
        if porcupine is not None:
            porcupine.delete()
        if audio_stream is not None:
            audio_stream.close()
        if pa is not None:
            pa.terminate()

if __name__ == '__main__':
    main()

Try to run the Windows version of the code and notice that it works. Then try to run the linux version of the code on a Raspberry Pi and observe the error

Expected Behavior

The code should run on linux. This is just a small version of the whole code I am trying to run. Here is my complete code, which should accept a wake word, allow me to dictate a prompt, transcribe the prompt to text, send the test to DALLE-3 to generate an image, display that image on my inky impressions.

import os
import requests
import pyaudio
import wave
import struct
from dotenv import load_dotenv
from PIL import Image
from io import BytesIO
from pathlib import Path
from inky.auto import auto
from gpiozero import Button
import signal
import openai
import pvporcupine
import pvcobra

def wait_for_wake_word(pico_key):
    porcupine = pvporcupine.create(access_key=pico_key, keywords=["Art-Frame"])
    pa = pyaudio.PyAudio()
    stream = pa.open(format=pyaudio.paInt16, channels=1, rate=porcupine.sample_rate,
                     input=True, frames_per_buffer=porcupine.frame_length)

    print("Listening for the wake word...")
    while True:
        pcm = stream.read(porcupine.frame_length)
        pcm = struct.unpack_from("h" * porcupine.frame_length, pcm)
        keyword_index = porcupine.process(pcm)
        if keyword_index >= 0:
            print("Wake word detected")
            break

    stream.stop_stream()
    stream.close()
    pa.terminate()
    porcupine.delete()

def record_audio_until_silence(pico_key):
    cobra = pvcobra.create(access_key=pico_key)
    pa = pyaudio.PyAudio()
    stream = pa.open(format=pyaudio.paInt16, rate=cobra.sample_rate, channels=1,
                     input=True, frames_per_buffer=cobra.frame_length)

    print("Recording...")
    frames = []
    last_voice_time = time.time()
    while True:
        pcm = stream.read(cobra.frame_length)
        pcm = struct.unpack_from("h" * cobra.frame_length, pcm)
        if cobra.process(pcm) > 0.2:
            last_voice_time = time.time()
            frames.append(pcm)
        elif (time.time() - last_voice_time) > 3:
            print("Silence detected, stopping recording.")
            break

    stream.stop_stream()
    stream.close()
    pa.terminate()
    cobra.delete()

    return b''.join(frames)

def transcribe(audio_data, api_key):
    # Save audio to a temporary file
    wav_path = Path("temp_recording.wav")
    with wave.open(str(wav_path), 'wb') as wf:
        wf.setnchannels(1)
        wf.setsampwidth(pyaudio.get_sample_size(pyaudio.paInt16))
        wf.setframerate(16000)
        wf.writeframes(audio_data)

    # Transcribe audio
    with open(wav_path, 'rb') as audio_file:
        transcription_response = openai.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            api_key=api_key
        )
    transcription = transcription_response
    print("Transcription:", transcription)
    return transcription

def generate_image(prompt, api_key, inky_display):
    response = openai.Image.create(
        prompt=prompt,
        n=1,
        size="1024x1024",
        model="dall-e-3",
        api_key=api_key
    )
    image_url = response['data'][0]['url']
    image_response = requests.get(image_url)
    image_bytes = image_response.content
    image = Image.open(BytesIO(image_bytes)).resize(inky_display.resolution)
    return image

def main():
    load_dotenv()
    openai_api_key = os.getenv('OPENAI_API_KEY')
    picovoice_api_key = os.getenv('PICOVOICE_API_KEY')
    inky_display = auto(ask_user=True, verbose=True)
    button_a = Button(5)

    while True:
        wait_for_wake_word(picovoice_api_key)
        audio_data = record_audio_until_silence(picovoice_api_key)
        prompt = transcribe(audio_data, openai_api_key)
        image = generate_image(prompt, openai_api_key, inky_display)
        inky_display.set_image(image)
        inky_display.show()

if __name__ == '__main__':
    main()
ErisMik commented 6 months ago

Thanks for reaching out. Typically a PorcupineActivationRefusedError means your account has been flagged by Picovoice Audit System. Picovoice Audit System can delete accounts in case of Picovoice Terms of Use violations, such as suspicious activities, creating multiple accounts, providing false or inaccurate information.

If you think there is a mistake, please send an email to hello@picovoice.ai with your name, surname, country, city and project details. We’ll investigate it further.

EA914 commented 6 months ago

Thank you Eris, I just sent an email with an explanation. I hope to hear from you soon.

MuhammadBilal848 commented 6 months ago

Have you checked the docs and existing issues?

  • [x] I have read all of the relevant Picovoice Porcupine docs
  • [x] I have searched the existing issues for Porcupine

SDK

Python

Porcupine package version

3.0.2

Framework version

Pythonh 3.11

Platform

Raspberry Pi

OS/Browser version

Deboam GNU/Linux 12 (bookworm)

Describe the bug

This is an output of the exact error when I try to run my code.

Traceback (most recent call last):
  File "/home/evan/Documents/Python/Gemini Images/inky041924.py", line 113, in <module>
    main()
  File "/home/evan/Documents/Python/Gemini Images/inky041924.py", line 105, in main
    wait_for_wake_word(picovoice_api_key)
  File "/home/evan/Documents/Python/Gemini Images/inky041924.py", line 18, in wait_for_wake_word
    porcupine = pvporcupine.create(access_key=pico_key, keywords=["Art-Frame"])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/evan/Documents/Python/Gemini Images/myenv/lib/python3.11/site-packages/pvporcupine/_factory.py", line 69, in create
    return Porcupine(
           ^^^^^^^^^^
  File "/home/evan/Documents/Python/Gemini Images/myenv/lib/python3.11/site-packages/pvporcupine/_porcupine.py", line 198, in __init__
    raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](
pvporcupine._porcupine.PorcupineActivationRefusedError: Initialization failed:
  [0] Picovoice Error (code `00000136`)
  [1] Picovoice Error (code `00000136`)
  [2] Picovoice Error (code `00000136`)

The code equivalent (where I am not outputting the image it displays to the inky display, but instead running this on Windows and opening the image it generates in the windows file viewer, works perfectly. This bug seems to be specific to Raspberry Pi OS

Steps To Reproduce

I created a test script to run my code in windows, which works:

import pvporcupine
import pyaudio
import struct

def main():
  # Configuration parameters
  access_key = "ACCESS_KEY_HERE"
  keyword_path = r"C:\Users\Evan Alexander\AppData\Local\Programs\Python\Python312\Lib\site-packages\pvporcupine\resources\keyword_files\windows\Art-Frame_en_windows_v3_0_0.ppn"

  try:
      # Create a Porcupine object with the given access key and keyword file
      porcupine = pvporcupine.create(access_key=access_key, keyword_paths=[keyword_path])

      # Set up audio input stream
      pa = pyaudio.PyAudio()
      audio_stream = pa.open(
          rate=porcupine.sample_rate,
          channels=1,
          format=pyaudio.paInt16,
          input=True,
          frames_per_buffer=porcupine.frame_length
      )

      print("Listening for the wake word 'Art-Frame'...")

      # Main loop to process audio frames
      while True:
          # Read frame from audio input stream
          pcm_frame = audio_stream.read(porcupine.frame_length)
          pcm_frame = struct.unpack_from("h" * porcupine.frame_length, pcm_frame)

          # Process frame to detect keyword
          result = porcupine.process(pcm_frame)
          if result >= 0:
              print("Wake word 'Art-Frame' detected!")

  except KeyboardInterrupt:
      print("Exiting...")
  finally:
      # Clean up resources
      if porcupine is not None:
          porcupine.delete()
      if audio_stream is not None:
          audio_stream.close()
      if pa is not None:
          pa.terminate()

if __name__ == '__main__':
  main()

The equivalent code in linux returns the error:

import pvporcupine
import pyaudio
import struct

def main():
  # Configuration parameters
  access_key = "ACCESS_KEY_HERE" 
  keyword_path = "/home/evan/.local/lib/python3.11/site-packages/pvporcupine/resources/keyword_files/raspberry-pi/Art-Frame_raspberry-pi.ppn"
  # Adjust the path to the location where you have saved the keyword file on your Raspberry Pi

  try:
      # Create a Porcupine object with the given access key and keyword file
      porcupine = pvporcupine.create(access_key=access_key, keyword_paths=[keyword_path])

      # Set up audio input stream
      pa = pyaudio.PyAudio()
      audio_stream = pa.open(
          rate=porcupine.sample_rate,
          channels=1,
          format=pyaudio.paInt16,
          input=True,
          frames_per_buffer=porcupine.frame_length
      )

      print("Listening for the wake word 'Art-Frame'...")

      # Main loop to process audio frames
      while True:
          # Read frame from audio input stream
          pcm_frame = audio_stream.read(porcupine.frame_length)
          pcm_frame = struct.unpack_from("h" * porcupine.frame_length, pcm_frame)

          # Process frame to detect keyword
          result = porcupine.process(pcm_frame)
          if result >= 0:
              print("Wake word 'Art-Frame' detected!")

  except KeyboardInterrupt:
      print("Exiting...")
  finally:
      # Clean up resources
      if porcupine is not None:
          porcupine.delete()
      if audio_stream is not None:
          audio_stream.close()
      if pa is not None:
          pa.terminate()

if __name__ == '__main__':
  main()

Try to run the Windows version of the code and notice that it works. Then try to run the linux version of the code on a Raspberry Pi and observe the error

Expected Behavior

The code should run on linux. This is just a small version of the whole code I am trying to run. Here is my complete code, which should accept a wake word, allow me to dictate a prompt, transcribe the prompt to text, send the test to DALLE-3 to generate an image, display that image on my inky impressions.

import os
import requests
import pyaudio
import wave
import struct
from dotenv import load_dotenv
from PIL import Image
from io import BytesIO
from pathlib import Path
from inky.auto import auto
from gpiozero import Button
import signal
import openai
import pvporcupine
import pvcobra

def wait_for_wake_word(pico_key):
  porcupine = pvporcupine.create(access_key=pico_key, keywords=["Art-Frame"])
  pa = pyaudio.PyAudio()
  stream = pa.open(format=pyaudio.paInt16, channels=1, rate=porcupine.sample_rate,
                   input=True, frames_per_buffer=porcupine.frame_length)

  print("Listening for the wake word...")
  while True:
      pcm = stream.read(porcupine.frame_length)
      pcm = struct.unpack_from("h" * porcupine.frame_length, pcm)
      keyword_index = porcupine.process(pcm)
      if keyword_index >= 0:
          print("Wake word detected")
          break

  stream.stop_stream()
  stream.close()
  pa.terminate()
  porcupine.delete()

def record_audio_until_silence(pico_key):
  cobra = pvcobra.create(access_key=pico_key)
  pa = pyaudio.PyAudio()
  stream = pa.open(format=pyaudio.paInt16, rate=cobra.sample_rate, channels=1,
                   input=True, frames_per_buffer=cobra.frame_length)

  print("Recording...")
  frames = []
  last_voice_time = time.time()
  while True:
      pcm = stream.read(cobra.frame_length)
      pcm = struct.unpack_from("h" * cobra.frame_length, pcm)
      if cobra.process(pcm) > 0.2:
          last_voice_time = time.time()
          frames.append(pcm)
      elif (time.time() - last_voice_time) > 3:
          print("Silence detected, stopping recording.")
          break

  stream.stop_stream()
  stream.close()
  pa.terminate()
  cobra.delete()

  return b''.join(frames)

def transcribe(audio_data, api_key):
  # Save audio to a temporary file
  wav_path = Path("temp_recording.wav")
  with wave.open(str(wav_path), 'wb') as wf:
      wf.setnchannels(1)
      wf.setsampwidth(pyaudio.get_sample_size(pyaudio.paInt16))
      wf.setframerate(16000)
      wf.writeframes(audio_data)

  # Transcribe audio
  with open(wav_path, 'rb') as audio_file:
      transcription_response = openai.audio.transcriptions.create(
          model="whisper-1",
          file=audio_file,
          api_key=api_key
      )
  transcription = transcription_response
  print("Transcription:", transcription)
  return transcription

def generate_image(prompt, api_key, inky_display):
  response = openai.Image.create(
      prompt=prompt,
      n=1,
      size="1024x1024",
      model="dall-e-3",
      api_key=api_key
  )
  image_url = response['data'][0]['url']
  image_response = requests.get(image_url)
  image_bytes = image_response.content
  image = Image.open(BytesIO(image_bytes)).resize(inky_display.resolution)
  return image

def main():
  load_dotenv()
  openai_api_key = os.getenv('OPENAI_API_KEY')
  picovoice_api_key = os.getenv('PICOVOICE_API_KEY')
  inky_display = auto(ask_user=True, verbose=True)
  button_a = Button(5)

  while True:
      wait_for_wake_word(picovoice_api_key)
      audio_data = record_audio_until_silence(picovoice_api_key)
      prompt = transcribe(audio_data, openai_api_key)
      image = generate_image(prompt, openai_api_key, inky_display)
      inky_display.set_image(image)
      inky_display.show()

if __name__ == '__main__':
  main()

I tried this code of yours:

import pvporcupine
import pyaudio
import struct

def main():
    # Configuration parameters
    access_key = "MY_API"
    keyword_path = r"C:\Users\Bilal\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pvporcupine\resources\keyword_files\windows\helfen_windows.ppn"

    try:
        # Create a Porcupine object with the given access key and keyword file
        porcupine = pvporcupine.create(access_key=access_key, keyword_paths=[keyword_path])

        # Set up audio input stream
        pa = pyaudio.PyAudio()
        audio_stream = pa.open(
            rate=porcupine.sample_rate,
            channels=1,
            format=pyaudio.paInt16,
            input=True,
            frames_per_buffer=porcupine.frame_length
        )

        print("Listening for the wake word 'Helfen'...")

        # Main loop to process audio frames
        while True:
            # Read frame from audio input stream
            pcm_frame = audio_stream.read(porcupine.frame_length)
            pcm_frame = struct.unpack_from("h" * porcupine.frame_length, pcm_frame)

            # Process frame to detect keyword
            result = porcupine.process(pcm_frame)
            if result >= 0:
                print("Wake word 'Helfen' detected!")

    except KeyboardInterrupt:
        print("Exiting...")
    finally:
        # Clean up resources
        if porcupine is not None:
            porcupine.delete()
        if audio_stream is not None:
            audio_stream.close()
        if pa is not None:
            pa.terminate()

if __name__ == '__main__':
    main()

But I'm getting this error:

Traceback (most recent call last):
  File "F:\Projects\PicoVoice\pcpine.py", line 13, in main
    porcupine = pvporcupine.create(access_key=access_key, keyword_paths=[keyword_path])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Bilal\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pvporcupine\_factory.py", line 69, in create
    return Porcupine(
           ^^^^^^^^^^
  File "C:\Users\Bilal\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pvporcupine\_porcupine.py", line 198, in __init__
    raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](
pvporcupine._porcupine.PorcupineInvalidArgumentError: Initialization failed:
  [0] Keyword file (.ppn) file has incorrect format or belongs to a different platform.
  [1] Picovoice Error (code `00000136`)
  [2] Loading keyword file at `C:\Users\Bilal\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pvporcupine\resources\keyword_files\windows\helfen_windows.ppn` failed with `INVALID_ARGUME

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "F:\Projects\PicoVoice\pcpine.py", line 50, in <module>
    main()
  File "F:\Projects\PicoVoice\pcpine.py", line 42, in main
    if porcupine is not None:
       ^^^^^^^^^
UnboundLocalError: cannot access local variable 'porcupine' where it is not associated with a value

Is there any way to solve this? Btw I trained the file on the Porcupine console and got my .ppn file and I put it inside the keywords file where all other files are available.

EA914 commented 6 months ago

@MuhammadBilal848 I'm not sure. I suggest opening a separate issue with Pico. I learned how to use the wake word by following this guy's code if this helps: https://github.com/DevMiser/AI_Art_Frame/blob/main/AIArtFrame.py

I also think your keyword file is in the wrong place. It should be in AppData local yes, but in sitepackages where all your other python libraries are. Looks like you're adding it to some sort of cache folder?

Honestly I'm not sure sorry. It has to be a configuration issue though because my code works but again I'm not an expert

MuhammadBilal848 commented 6 months ago

@MuhammadBilal848 I'm not sure. I suggest opening a separate issue with Pico. I learned how to use the wake word by following this guy's code if this helps: https://github.com/DevMiser/AI_Art_Frame/blob/main/AIArtFrame.py

I also think your keyword file is in the wrong place. It should be in AppData local yes, but in sitepackages where all your other python libraries are. Looks like you're adding it to some sort of cache folder?

Honestly I'm not sure sorry. It has to be a configuration issue though because my code works but again I'm not an expert

I found out the problem. I exported the model of Android Build while I was trying to run it on Windows. I downloaded the model on windows and now it is working.