{"id":31588611,"url":"https://github.com/piyopiyoex/open_jtalk_elixir","last_synced_at":"2025-12-12T00:10:55.619Z","repository":{"id":313198503,"uuid":"1049744071","full_name":"piyopiyoex/open_jtalk_elixir","owner":"piyopiyoex","description":"Use Open JTalk in Elixir","archived":false,"fork":false,"pushed_at":"2025-09-30T06:03:00.000Z","size":70820,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-30T08:18:13.439Z","etag":null,"topics":["elixir","mecab","openjtalk"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/open_jtalk_elixir","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piyopiyoex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-03T12:39:31.000Z","updated_at":"2025-09-23T02:44:48.000Z","dependencies_parsed_at":"2025-09-04T14:37:04.257Z","dependency_job_id":"138ddb8c-2fd4-466c-ab33-ef1c85ce8e87","html_url":"https://github.com/piyopiyoex/open_jtalk_elixir","commit_stats":null,"previous_names":["mnishiguchi/open_jtalk_elixir"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/piyopiyoex/open_jtalk_elixir","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piyopiyoex%2Fopen_jtalk_elixir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piyopiyoex%2Fopen_jtalk_elixir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piyopiyoex%2Fopen_jtalk_elixir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piyopiyoex%2Fopen_jtalk_elixir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piyopiyoex","download_url":"https://codeload.github.com/piyopiyoex/open_jtalk_elixir/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piyopiyoex%2Fopen_jtalk_elixir/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278435883,"owners_count":25986493,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","mecab","openjtalk"],"created_at":"2025-10-06T02:11:29.254Z","updated_at":"2025-10-06T02:12:00.547Z","avatar_url":"https://github.com/piyopiyoex.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# open_jtalk_elixir\n\n[![Hex version](https://img.shields.io/hexpm/v/open_jtalk_elixir.svg \"Hex version\")](https://hex.pm/packages/open_jtalk_elixir)\n[![CI](https://github.com/mnishiguchi/open_jtalk_elixir/actions/workflows/ci.yml/badge.svg)](https://github.com/mnishiguchi/open_jtalk_elixir/actions/workflows/ci.yml)\n\n\u003c!-- MODULEDOC --\u003e\n\nUse Open JTalk from Elixir. This package builds a local `open_jtalk` CLI and,\nby default, bundles a UTF-8 dictionary and an HTS voice (you can disable this),\nexposing convenient functions:\n\n- `OpenJTalk.say/2` — synthesize and play via a system audio player\n- `OpenJTalk.to_wav_file/2` — synthesize text to a WAV file\n- `OpenJTalk.to_wav_binary/2` — synthesize and return WAV bytes\n- `OpenJTalk.Wav.concat_binaries/1` — merge multiple WAV binaries (same format)\n- `OpenJTalk.Wav.concat_files/1` — merge multiple WAV files from paths (same format)\n\n## Install\n\nAdd the dependency to your `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:open_jtalk_elixir, \"~\u003e 0.3\"}\n  ]\nend\n```\n\nThen:\n\n```bash\nmix deps.get\nmix compile\n```\n\nOn first compile the project may download and build MeCab, HTS Engine API,\nand Open JTalk. By default it also downloads and bundles a UTF-8 dictionary\nand a Mei voice into `priv/` (you can turn this off with\n`OPENJTALK_BUNDLE_ASSETS=0`).\n\n### Build requirements\n\nYou’ll need common build tools: `gcc`/`g++`, `make`, `curl`, `tar`, `unzip`.\nOn macOS Xcode Command Line Tools are sufficient.\n\nOptional environment flags (honored by the Makefile):\n\n- `OPENJTALK_FULL_STATIC=1` — attempt a fully static `open_jtalk` (Linux only; requires static libstdc++)\n- `OPENJTALK_BUNDLE_ASSETS=0|1` — whether to bundle dictionary/voice into `priv/`\n\n### Tested platforms\n\nHost builds (compile and run on the same machine):\n\n- Linux x86_64\n- Linux aarch64\n- macOS 14 (arm64, Apple Silicon)\n\nCross-compile (host → target):\n\n- Linux x86_64 → Nerves rpi4 (aarch64)\n\n## Quick start\n\n```elixir\n# play via system audio player (aplay/paplay/afplay/play)\nOpenJTalk.say(\"元氣ですかあ 、元氣が有れば、なんでもできる\")\n```\n\n### Options\n\nAll synthesis calls accept the same options (values are clamped):\n\n- `:timbre` — voice color offset `-0.8..0.8` (default `0.0`)\n- `:pitch_shift` — semitones `-24..24` (default `0`)\n- `:rate` — speaking speed `0.5..2.0` (default `1.0`)\n- `:gain` — output gain in dB (default `0`)\n- `:voice` — path to a `.htsvoice` file (optional)\n- `:dictionary` — path to a directory containing `sys.dic` (optional)\n- `:timeout` — max runtime in ms (default `20_000`)\n- `:out` — output WAV path (only for `to_wav_file/2`)\n\n### Concatenate WAVs\n\nYou can combine multiple WAVs (same format: channels/rate/bit depth/etc.) into one:\n\n```elixir\n{:ok, a} = OpenJTalk.to_wav_binary(\"これは一つ目。\")\n{:ok, b} = OpenJTalk.to_wav_binary(\"これは二つ目。\")\n{:ok, c} = OpenJTalk.to_wav_binary(\"これは三つ目。\")\n\n{:ok, merged} = OpenJTalk.Wav.concat_binaries([a, b, c])\n# or from files:\n# {:ok, merged} = OpenJTalk.Wav.concat_files([\"a.wav\", \"b.wav\", \"c.wav\"])\n```\n\n\u003c!-- MODULEDOC --\u003e\n\n## How asset resolution works\n\nThe package resolves required assets in this order:\n\n1. Environment variable override\n2. Bundled asset in `priv/`\n3. System-installed location\n\n### CLI binary (`open_jtalk`)\n\n- **Env:** `OPENJTALK_CLI` — full path to `open_jtalk`.\n- **Bundled:** `priv/bin/open_jtalk` (built during compile).\n- **System:** `open_jtalk` found on `$PATH`.\n\n### Dictionary (`sys.dic`)\n\n- **Env:** `OPENJTALK_DICTIONARY_DIR` — directory containing `sys.dic`.\n- **Bundled:** `priv/dictionary/sys.dic` or any `priv/dictionary/**/sys.dic` (e.g. `naist-jdic`).\n- **System:** common locations such as `/var/lib/mecab/dic/open-jtalk/naist-jdic`,\n  `/usr/lib/*/mecab/dic/open-jtalk/naist-jdic`, etc.\n\n### Voice (`.htsvoice`)\n\n- **Env:** `OPENJTALK_VOICE` — path to a `.htsvoice` file.\n- **Bundled:** first file matching `priv/voices/**/*.htsvoice`.\n- **System:** standard locations like `/usr/share/hts-voice/**` or `/usr/local/share/hts-voice/**`.\n\nIf you change environment variables at runtime (or move files), refresh the\ncached paths:\n\n```elixir\nOpenJTalk.Assets.reset_cache()\n```\n\n## Using with Nerves\n\nThis library is Nerves-aware. When `MIX_TARGET` is set the build defaults to:\n\n- `OPENJTALK_FULL_STATIC=1` — try to statically link the CLI on Linux targets when possible\n- `OPENJTALK_BUNDLE_ASSETS=1` — bundle CLI, dictionary, and voice into `priv/`\n\nSo for many projects no extra configuration is needed.\n\n### Quick Nerves flow\n\n```bash\nexport MIX_TARGET=rpi4\nmix deps.get\nmix compile\nmix firmware\n```\n\nOn the device:\n\n```elixir\n{:ok, info} = OpenJTalk.info()\n# bundled assets should show up as :bundled\n\nOpenJTalk.say(\"こんにちは\")\n```\n\n### Audio on Nerves\n\n`OpenJTalk.say/2` requires a system audio player. Most Nerves images use ALSA\n`aplay`. If your image does not include a player:\n\n- add one to the system image, or\n- use `OpenJTalk.to_wav_file/2` and play the WAV with your chosen mechanism.\n\n### Firmware size notes\n\nBundling the full dictionary + voice + binary increases firmware size. Approximate\n(uncompressed) sizes:\n\n- Dictionary: ~103 MB\n- Mei voice: ~2.2 MB\n- CLI binary: ~2.4 MB\n\nIf that’s too large you can avoid bundling at compile time and provision assets\nseparately (rootfs overlay, `/data`, OTA, etc.):\n\n```bash\nMIX_TARGET=rpi4 OPENJTALK_BUNDLE_ASSETS=0 mix deps.compile open_jtalk_elixir\n```\n\nThen point the library to the provisioned assets (for example in\n`config/runtime.exs`):\n\n```elixir\nSystem.put_env(\"OPENJTALK_CLI\", \"/data/open_jtalk/bin/open_jtalk\")\nSystem.put_env(\"OPENJTALK_DICTIONARY_DIR\", \"/data/open_jtalk/dic\")\nSystem.put_env(\"OPENJTALK_VOICE\", \"/data/open_jtalk/voices/mei_normal.htsvoice\")\n\nOpenJTalk.Assets.reset_cache()\n```\n\nHow you provision those files into your image is outside the scope of this\nlibrary.\n\n## Third-party components and licenses\n\nThis package does not redistribute third-party assets by default.\nAt compile time it may download and build the following components:\n\n- **Open JTalk 1.11**\n  - License: Modified BSD (3-Clause)\n  - Source: http://open-jtalk.sourceforge.net/\n- **HTS Engine API 1.10**\n  - License: Modified BSD (3-Clause)\n  - Source: http://hts-engine.sourceforge.net/\n- **MeCab 0.996**\n  - License: Tri-licensed (GPL / LGPL / BSD); used under BSD terms\n  - Source: https://taku910.github.io/mecab/\n- **Open JTalk Dictionary (NAIST-JDIC UTF-8) 1.11**\n  - License: BSD-style by NAIST\n  - Source: https://sourceforge.net/projects/open-jtalk/files/Dictionary/\n- **HTS Voice “Mei” (MMDAgent_Example 1.8)**\n  - License: CC BY 3.0\n  - Source: https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/\n  - Attribution: “HTS Voice ‘Mei’ © Nagoya Institute of Technology, licensed CC BY 3.0.”\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiyopiyoex%2Fopen_jtalk_elixir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiyopiyoex%2Fopen_jtalk_elixir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiyopiyoex%2Fopen_jtalk_elixir/lists"}