oremi-ohunerin


Nameoremi-ohunerin JSON
Version 2.0.2 PyPI version JSON
download
home_pagehttps://gitlab.com/demsking/oremi-ohunerin
SummaryReal-time ambient sound and wake word detection
upload_time2025-01-26 17:06:37
maintainerNone
docs_urlNone
authorSébastien Demanou
requires_python<3.12,>=3.11
licenseApache-2.0
keywords sound detection wakeword
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Oremi Ohunerin

[![Buy me a beer](https://img.shields.io/badge/Buy%20me-a%20beer-1f425f.svg)](https://www.buymeacoffee.com/demsking)

Oremi Ohunerin is the real-time audio detection component of the Oremi Personal
Assistant project, operating as a websocket server proficient in identifying
environmental sounds and the specific wake word to activate Oremi.

Leveraging cutting-edge technologies such as Tensorflow YAMNet for comprehensive
audio detection and PocketSphinx for precise wake word identification, this
component ensures accurate recognition of various sound categories, including
but not limited to shouts, laughter, crying, and more.

Derived from the Yoruba term "ohun erin," meaning "sound detection," Ohunerin
embodies the essence of its function, facilitating seamless integration of
auditory cues into the Oremi ecosystem, thus enhancing user experience and
interaction.

## Table of Contents

- [Getting Started with Oremi Ohunerin](#getting-started-with-oremi-ohunerin)
- [Environment Variables](#environment-variables)
- [Starting Ohunerin with Certificates](#starting-ohunerin-with-certificates)
- [Oremi Ohunerin Protocol](#oremi-ohunerin-protocol)
  * [Initialization](#initialization)
  * [Sound Detection](#sound-detection)
  * [Connection Closure Codes](#connection-closure-codes)
  * [Example Implementation](#example-implementation)
- [Oremi Ohunerin Listener](#oremi-ohunerin-listener)
- [Contribute](#contribute)
- [Versioning](#versioning)
- [License](#license)

## Getting Started with Oremi Ohunerin

The easiest way to use Oremi Ohunerin is with Docker. Start with Docker for a
quick setup. Follow these steps:

**Using Docker**

Use the official Docker image [`demsking/oremi-ohunerin`](https://hub.docker.com/r/demsking/oremi-ohunerin)
to run Oremi Ohunerin:

```sh
docker run -d \
  --env-file <path_to_env_file> \
  -p 5023:5023 \
  demsking/oremi-ohunerin
```

Replace `<path_to_env_file>` with the path to your environment variable file
containing the necessary configurations.

This pulls Oremi Ohunerin and starts it on port `5023`.

**Alternative Installation**

If you prefer installing Oremi Ohunerin directly, you'll need to install the
required YAMNet model manualy.

1. Download the install script from the Oremi Ohunerin repository:
   [install-model.sh](https://gitlab.com/demsking/oremi-ohunerin/-/raw/main/scripts/install-model.sh?inline=false)

2. Make the script executable:

   ```bash
   chmod +x install-model.sh
   ```

3. Run the script with the following command:

   ```sh
   # install Yamnet model to "~/.cache/tensorflow/models"
   ./install-model.sh ~/.cache/tensorflow/models/yamnet.tflite
   ```

Now you can install Oremi Ohunerin from PyPi:

```sh
pip install oremi-ohunerin
```

After installation, start Oremi Ohunerin using the provided command.

```sh
usage: oremi-ohunerin [-h] -m MODEL [-t THRESHOLD] [-c CONFIG] [--host HOST] [-p PORT] [--cert-file CERT_FILE] [--key-file KEY_FILE] [--password PASSWORD] [-v]

Real-time ambient sound and wake word detection

options:
  -h, --help            show this help message and exit
  -m MODEL, --model MODEL
                        Path to the TensorFlow Lite model filename (required).
  -t THRESHOLD, --threshold THRESHOLD
                        Detection threshold for filtering predictions (default: 0.1).
  -c CONFIG, --config CONFIG
                        Path to the configuration file (default: config.json).
  --host HOST           Host address to listen on (default: 127.0.0.1).
  -p PORT, --port PORT  Port number to listen on (default: 5023).
  --cert-file CERT_FILE
                        Path to the certificate file for secure connection.
  --key-file KEY_FILE   Path to the private key file for secure connection.
  --password PASSWORD   Password to unlock the private key (if protected by a password).
  -v, --version         Show the version of the application.
```

## Environment Variables

The following environment variables can be used to configure the Oremi Ohunerin
Docker containers:

| Variable        | Description                     | Default Value |
|-----------------|---------------------------------|---------------|
| LOG_LEVEL       | Logging level                   | "info"        |
| LOG_FILE        | Log file path                   |               |

## Starting Ohunerin with Certificates

To start the Oremi Ohunerin with a certificate, you can use the `--cert-file`
and `--key-file` options to specify the certificate and private key files.
Additionally, if your private key is password-protected, you can use the
`--password` option to provide the password. Here's how to proceed:

1. **Generate a Self-Signed SSL Certificate (For Testing):**

   If you're testing Oremi Ohunerin locally, you can generate a self-signed
   SSL certificate.
   Follow these steps to generate a self-signed certificate using OpenSSL:

   ```sh
   # Generate a self-signed certificate
   openssl req -x509 -nodes -new -sha256 -days 365 -newkey rsa:2048 \
     -subj "/C=CM/CN=localhost" \
     -keyout key.pem \
     -out cert.pem
   ```

   It's important to note that these certificates are self-signed, which means
   they are not issued by a recognized Certificate Authority (CA). While
   suitable for testing and development purposes, self-signed certificates may
   trigger security warnings in browsers and other client applications.

   Please note that this is a simplified example for generating self-signed
   certificates for testing purposes. In production environments, it's
   recommended to obtain SSL certificates from a trusted Certificate
   Authority (CA) like [Let's Encrypt](https://letsencrypt.org/) to ensure
   security and proper authentication..
   Let's Encrypt provides free and automated certificates that are recognized
   by most browsers and clients.

2. **Start Ohunerin using Docker:**

   The quickest way to start the Oremi Ohunerin server with certificates is by
   using Docker. Run the following command in your terminal:

   ```sh
   docker run -d \
      -p 5023:5023 \
      -v ~/.cache/tensorflow/models/yamnet.tflite:/var/oremi/models/yamnet.tflite \
      -v /path/to/cert.pem:/cert.pem \
      -v /path/to/key.pem:/key.pem \
    demsking/oremi-ohunerin \
      --cert-file /cert.pem \
      --key-file /key.pem \
      --password your_private_key_password
   ```

   > Replace `/path/to/cert.pem`, `/path/to/key.pem`, and
   > `your_private_key_password` with the appropriate values.

   This command mounts the certificate and key files into the Docker container
   and starts the server.

## Oremi Ohunerin Protocol

Oremi Ohunerin websocket server listens on port `5023` for incoming connections
from clients, which can continuously stream audio data. Once connected, clients
can send audio data in `bytes`, and the server will process it in real-time,
detecting sounds and sending JSON messages back to the client when a sound is
recognized.

The protocol involves an initialization step where the client provides essential
details such as the number of audio channels, sample rate, block size, language,
and features to enable. Once the session is initialized, the client can
continuously stream audio data to the server. The server processes the audio in
real-time and sends JSON messages back to the client when it detects specific
sounds, such as wake words or predefined songs.

The section outlines the message structures, initialization process, sound
detection mechanism, and possible connection closure codes. Developers can use
this protocol documentation as a reference to interact with the server and
build their applications accordingly.

### Initialization

**1. Client**

When a client connects to the server, it must send an initial
[JSON initiation message](https://gitlab.com/demsking/oremi-ohunerin/blob/main/schemas/InitMessage.json)
**within 5 seconds** or else the connection will be closed with code `1002`
and reason `Init Timeout`.

```json
{
  "type": "init",
  "language": "fr",
  "features": [
    { "name": "wakeword-detection" },
    { "name": "sound-detection" }
  ]
}
```

**2. Server**

The server responds with an initialization acknowledgment, providing details
about available languages for wakeword detection:

```json
{
  "type": "init",
  "server": "oremi-ohunerin/1.0.0",
  "status": "ready",
  "languages": ["en", "fr"]
}
```

**Note:** If the client doesn't send the initialization message within **5
seconds**, the server will close the connection with code `1002` and reason
`Init Timeout`.

### Sound Detection

**1. Client**

Once the session is initialized, the client streams audio data in bytes to the
server, with an audio frequency of **16000Hz** and a **single channel**.

**2. Server**

The server processes the audio stream in real-time and sends a
[JSON sound message](https://gitlab.com/demsking/oremi-ohunerin/blob/main/schemas/DetectedSoundSchema.json)
when it detects a sound:

**Example for wakeword**

```json
{
  "type": "sound",
  "sound": "wakeword",
  "score": 1.0,
  "datetime": "2023-08-02T20:33:22.805154"
}
```

**Example for cough**

```json
{
  "type": "sound",
  "sound": "cough",
  "score": 0.4140625,
  "datetime": "2023-08-02T20:41:05.058204"
}
```

### Connection Closure Codes

Possible connection closure codes:

- `1000`: Indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled.
- `1002`: Init Timeout
- `1003`: Invalid Message
- `4000`: Unexpected Error

### Example Implementation

For an example of how to implement a client for the "Oremi Ohunerin", you can
refer to the [client.py file](https://gitlab.com/demsking/oremi-ohunerin/blob/main/client.py)
in the GitLab repository.
The example demonstrates how to connect to the server, send audio data, and
handle the JSON messages received from the server.

## Oremi Ohunerin Listener

The **Oremi Ohunerin Listener** is a complementary component designed to work
seamlessly with the Oremi Ohunerin WebSocket server. It listens to the
microphone, streams audio data to the Oremi Ohunerin server for real-time sound
detection, and publishes the detected sound results to an MQTT broker. This
makes it ideal for integrating sound detection capabilities into IoT systems or
other applications that rely on MQTT for communication.

For more details, visit the [Oremi Ohunerin Listener repository](https://gitlab.com/demsking/oremi-ohunerin-listener).

## Contribute

Please follow [CONTRIBUTING.md](https://gitlab.com/demsking/oremi-ohunerin/blob/main/CONTRIBUTING.md).

## Versioning

Given a version number `MAJOR.MINOR.PATCH`, increment the:

- `MAJOR` version when you make incompatible API changes,
- `MINOR` version when you add functionality in a backwards-compatible manner,
  and
- `PATCH` version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions
to the `MAJOR.MINOR.PATCH` format.

See [SemVer.org](https://semver.org/) for more details.

## License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License.
You may obtain a copy of the License at [LICENSE](https://gitlab.com/demsking/oremi-ohunerin/blob/main/LICENSE).


            

Raw data

            {
    "_id": null,
    "home_page": "https://gitlab.com/demsking/oremi-ohunerin",
    "name": "oremi-ohunerin",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<3.12,>=3.11",
    "maintainer_email": null,
    "keywords": "sound, detection, wakeword",
    "author": "S\u00e9bastien Demanou",
    "author_email": "demsking@gmail.com",
    "download_url": null,
    "platform": null,
    "description": "# Oremi Ohunerin\n\n[![Buy me a beer](https://img.shields.io/badge/Buy%20me-a%20beer-1f425f.svg)](https://www.buymeacoffee.com/demsking)\n\nOremi Ohunerin is the real-time audio detection component of the Oremi Personal\nAssistant project, operating as a websocket server proficient in identifying\nenvironmental sounds and the specific wake word to activate Oremi.\n\nLeveraging cutting-edge technologies such as Tensorflow YAMNet for comprehensive\naudio detection and PocketSphinx for precise wake word identification, this\ncomponent ensures accurate recognition of various sound categories, including\nbut not limited to shouts, laughter, crying, and more.\n\nDerived from the Yoruba term \"ohun erin,\" meaning \"sound detection,\" Ohunerin\nembodies the essence of its function, facilitating seamless integration of\nauditory cues into the Oremi ecosystem, thus enhancing user experience and\ninteraction.\n\n## Table of Contents\n\n- [Getting Started with Oremi Ohunerin](#getting-started-with-oremi-ohunerin)\n- [Environment Variables](#environment-variables)\n- [Starting Ohunerin with Certificates](#starting-ohunerin-with-certificates)\n- [Oremi Ohunerin Protocol](#oremi-ohunerin-protocol)\n  * [Initialization](#initialization)\n  * [Sound Detection](#sound-detection)\n  * [Connection Closure Codes](#connection-closure-codes)\n  * [Example Implementation](#example-implementation)\n- [Oremi Ohunerin Listener](#oremi-ohunerin-listener)\n- [Contribute](#contribute)\n- [Versioning](#versioning)\n- [License](#license)\n\n## Getting Started with Oremi Ohunerin\n\nThe easiest way to use Oremi Ohunerin is with Docker. Start with Docker for a\nquick setup. Follow these steps:\n\n**Using Docker**\n\nUse the official Docker image [`demsking/oremi-ohunerin`](https://hub.docker.com/r/demsking/oremi-ohunerin)\nto run Oremi Ohunerin:\n\n```sh\ndocker run -d \\\n  --env-file <path_to_env_file> \\\n  -p 5023:5023 \\\n  demsking/oremi-ohunerin\n```\n\nReplace `<path_to_env_file>` with the path to your environment variable file\ncontaining the necessary configurations.\n\nThis pulls Oremi Ohunerin and starts it on port `5023`.\n\n**Alternative Installation**\n\nIf you prefer installing Oremi Ohunerin directly, you'll need to install the\nrequired YAMNet model manualy.\n\n1. Download the install script from the Oremi Ohunerin repository:\n   [install-model.sh](https://gitlab.com/demsking/oremi-ohunerin/-/raw/main/scripts/install-model.sh?inline=false)\n\n2. Make the script executable:\n\n   ```bash\n   chmod +x install-model.sh\n   ```\n\n3. Run the script with the following command:\n\n   ```sh\n   # install Yamnet model to \"~/.cache/tensorflow/models\"\n   ./install-model.sh ~/.cache/tensorflow/models/yamnet.tflite\n   ```\n\nNow you can install Oremi Ohunerin from PyPi:\n\n```sh\npip install oremi-ohunerin\n```\n\nAfter installation, start Oremi Ohunerin using the provided command.\n\n```sh\nusage: oremi-ohunerin [-h] -m MODEL [-t THRESHOLD] [-c CONFIG] [--host HOST] [-p PORT] [--cert-file CERT_FILE] [--key-file KEY_FILE] [--password PASSWORD] [-v]\n\nReal-time ambient sound and wake word detection\n\noptions:\n  -h, --help            show this help message and exit\n  -m MODEL, --model MODEL\n                        Path to the TensorFlow Lite model filename (required).\n  -t THRESHOLD, --threshold THRESHOLD\n                        Detection threshold for filtering predictions (default: 0.1).\n  -c CONFIG, --config CONFIG\n                        Path to the configuration file (default: config.json).\n  --host HOST           Host address to listen on (default: 127.0.0.1).\n  -p PORT, --port PORT  Port number to listen on (default: 5023).\n  --cert-file CERT_FILE\n                        Path to the certificate file for secure connection.\n  --key-file KEY_FILE   Path to the private key file for secure connection.\n  --password PASSWORD   Password to unlock the private key (if protected by a password).\n  -v, --version         Show the version of the application.\n```\n\n## Environment Variables\n\nThe following environment variables can be used to configure the Oremi Ohunerin\nDocker containers:\n\n| Variable        | Description                     | Default Value |\n|-----------------|---------------------------------|---------------|\n| LOG_LEVEL       | Logging level                   | \"info\"        |\n| LOG_FILE        | Log file path                   |               |\n\n## Starting Ohunerin with Certificates\n\nTo start the Oremi Ohunerin with a certificate, you can use the `--cert-file`\nand `--key-file` options to specify the certificate and private key files.\nAdditionally, if your private key is password-protected, you can use the\n`--password` option to provide the password. Here's how to proceed:\n\n1. **Generate a Self-Signed SSL Certificate (For Testing):**\n\n   If you're testing Oremi Ohunerin locally, you can generate a self-signed\n   SSL certificate.\n   Follow these steps to generate a self-signed certificate using OpenSSL:\n\n   ```sh\n   # Generate a self-signed certificate\n   openssl req -x509 -nodes -new -sha256 -days 365 -newkey rsa:2048 \\\n     -subj \"/C=CM/CN=localhost\" \\\n     -keyout key.pem \\\n     -out cert.pem\n   ```\n\n   It's important to note that these certificates are self-signed, which means\n   they are not issued by a recognized Certificate Authority (CA). While\n   suitable for testing and development purposes, self-signed certificates may\n   trigger security warnings in browsers and other client applications.\n\n   Please note that this is a simplified example for generating self-signed\n   certificates for testing purposes. In production environments, it's\n   recommended to obtain SSL certificates from a trusted Certificate\n   Authority (CA) like [Let's Encrypt](https://letsencrypt.org/) to ensure\n   security and proper authentication..\n   Let's Encrypt provides free and automated certificates that are recognized\n   by most browsers and clients.\n\n2. **Start Ohunerin using Docker:**\n\n   The quickest way to start the Oremi Ohunerin server with certificates is by\n   using Docker. Run the following command in your terminal:\n\n   ```sh\n   docker run -d \\\n      -p 5023:5023 \\\n      -v ~/.cache/tensorflow/models/yamnet.tflite:/var/oremi/models/yamnet.tflite \\\n      -v /path/to/cert.pem:/cert.pem \\\n      -v /path/to/key.pem:/key.pem \\\n    demsking/oremi-ohunerin \\\n      --cert-file /cert.pem \\\n      --key-file /key.pem \\\n      --password your_private_key_password\n   ```\n\n   > Replace `/path/to/cert.pem`, `/path/to/key.pem`, and\n   > `your_private_key_password` with the appropriate values.\n\n   This command mounts the certificate and key files into the Docker container\n   and starts the server.\n\n## Oremi Ohunerin Protocol\n\nOremi Ohunerin websocket server listens on port `5023` for incoming connections\nfrom clients, which can continuously stream audio data. Once connected, clients\ncan send audio data in `bytes`, and the server will process it in real-time,\ndetecting sounds and sending JSON messages back to the client when a sound is\nrecognized.\n\nThe protocol involves an initialization step where the client provides essential\ndetails such as the number of audio channels, sample rate, block size, language,\nand features to enable. Once the session is initialized, the client can\ncontinuously stream audio data to the server. The server processes the audio in\nreal-time and sends JSON messages back to the client when it detects specific\nsounds, such as wake words or predefined songs.\n\nThe section outlines the message structures, initialization process, sound\ndetection mechanism, and possible connection closure codes. Developers can use\nthis protocol documentation as a reference to interact with the server and\nbuild their applications accordingly.\n\n### Initialization\n\n**1. Client**\n\nWhen a client connects to the server, it must send an initial\n[JSON initiation message](https://gitlab.com/demsking/oremi-ohunerin/blob/main/schemas/InitMessage.json)\n**within 5 seconds** or else the connection will be closed with code `1002`\nand reason `Init Timeout`.\n\n```json\n{\n  \"type\": \"init\",\n  \"language\": \"fr\",\n  \"features\": [\n    { \"name\": \"wakeword-detection\" },\n    { \"name\": \"sound-detection\" }\n  ]\n}\n```\n\n**2. Server**\n\nThe server responds with an initialization acknowledgment, providing details\nabout available languages for wakeword detection:\n\n```json\n{\n  \"type\": \"init\",\n  \"server\": \"oremi-ohunerin/1.0.0\",\n  \"status\": \"ready\",\n  \"languages\": [\"en\", \"fr\"]\n}\n```\n\n**Note:** If the client doesn't send the initialization message within **5\nseconds**, the server will close the connection with code `1002` and reason\n`Init Timeout`.\n\n### Sound Detection\n\n**1. Client**\n\nOnce the session is initialized, the client streams audio data in bytes to the\nserver, with an audio frequency of **16000Hz** and a **single channel**.\n\n**2. Server**\n\nThe server processes the audio stream in real-time and sends a\n[JSON sound message](https://gitlab.com/demsking/oremi-ohunerin/blob/main/schemas/DetectedSoundSchema.json)\nwhen it detects a sound:\n\n**Example for wakeword**\n\n```json\n{\n  \"type\": \"sound\",\n  \"sound\": \"wakeword\",\n  \"score\": 1.0,\n  \"datetime\": \"2023-08-02T20:33:22.805154\"\n}\n```\n\n**Example for cough**\n\n```json\n{\n  \"type\": \"sound\",\n  \"sound\": \"cough\",\n  \"score\": 0.4140625,\n  \"datetime\": \"2023-08-02T20:41:05.058204\"\n}\n```\n\n### Connection Closure Codes\n\nPossible connection closure codes:\n\n- `1000`: Indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled.\n- `1002`: Init Timeout\n- `1003`: Invalid Message\n- `4000`: Unexpected Error\n\n### Example Implementation\n\nFor an example of how to implement a client for the \"Oremi Ohunerin\", you can\nrefer to the [client.py file](https://gitlab.com/demsking/oremi-ohunerin/blob/main/client.py)\nin the GitLab repository.\nThe example demonstrates how to connect to the server, send audio data, and\nhandle the JSON messages received from the server.\n\n## Oremi Ohunerin Listener\n\nThe **Oremi Ohunerin Listener** is a complementary component designed to work\nseamlessly with the Oremi Ohunerin WebSocket server. It listens to the\nmicrophone, streams audio data to the Oremi Ohunerin server for real-time sound\ndetection, and publishes the detected sound results to an MQTT broker. This\nmakes it ideal for integrating sound detection capabilities into IoT systems or\nother applications that rely on MQTT for communication.\n\nFor more details, visit the [Oremi Ohunerin Listener repository](https://gitlab.com/demsking/oremi-ohunerin-listener).\n\n## Contribute\n\nPlease follow [CONTRIBUTING.md](https://gitlab.com/demsking/oremi-ohunerin/blob/main/CONTRIBUTING.md).\n\n## Versioning\n\nGiven a version number `MAJOR.MINOR.PATCH`, increment the:\n\n- `MAJOR` version when you make incompatible API changes,\n- `MINOR` version when you add functionality in a backwards-compatible manner,\n  and\n- `PATCH` version when you make backwards-compatible bug fixes.\n\nAdditional labels for pre-release and build metadata are available as extensions\nto the `MAJOR.MINOR.PATCH` format.\n\nSee [SemVer.org](https://semver.org/) for more details.\n\n## License\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthis file except in compliance with the License.\nYou may obtain a copy of the License at [LICENSE](https://gitlab.com/demsking/oremi-ohunerin/blob/main/LICENSE).\n\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "Real-time ambient sound and wake word detection",
    "version": "2.0.2",
    "project_urls": {
        "Documentation": "https://gitlab.com/demsking/oremi-ohunerin/-/blob/main/README.md",
        "Homepage": "https://gitlab.com/demsking/oremi-ohunerin",
        "Repository": "https://gitlab.com/demsking/oremi-ohunerin",
        "Say Thanks!": "https://www.buymeacoffee.com/demsking",
        "Source": "https://gitlab.com/demsking/oremi-ohunerin",
        "Tracker": "https://gitlab.com/demsking/oremi-ohunerin/-/issues"
    },
    "split_keywords": [
        "sound",
        " detection",
        " wakeword"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d4bf36bf6dd7e025962e31fdb733419c071de2a57fdd5473d91d4ccb60210e03",
                "md5": "fc629f50cc14940b8d12e799a41b6326",
                "sha256": "b5f916dda75b487b2ecc2042632ad99c6164e2e7bebbb614a6203d0df1a319f9"
            },
            "downloads": -1,
            "filename": "oremi_ohunerin-2.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fc629f50cc14940b8d12e799a41b6326",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<3.12,>=3.11",
            "size": 22584,
            "upload_time": "2025-01-26T17:06:37",
            "upload_time_iso_8601": "2025-01-26T17:06:37.254307Z",
            "url": "https://files.pythonhosted.org/packages/d4/bf/36bf6dd7e025962e31fdb733419c071de2a57fdd5473d91d4ccb60210e03/oremi_ohunerin-2.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-01-26 17:06:37",
    "github": false,
    "gitlab": true,
    "bitbucket": false,
    "codeberg": false,
    "gitlab_user": "demsking",
    "gitlab_project": "oremi-ohunerin",
    "lcname": "oremi-ohunerin"
}
        
Elapsed time: 0.78001s