# Copyright 2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
PYTHON_COMPAT=( python3_{12..14} )
DISTUTILS_USE_PEP517=setuptools
inherit distutils-r1 multiprocessing systemd xdg-utils
DESCRIPTION="Linux offline voice input method based on FunASR Paraformer"
HOMEPAGE="https://github.com/LeonardNJU/VocoType-linux"
# Model version (independent of software version)
VOCOTYPE_MODEL_REV="v2.0.5"
VOCOTYPE_ASR_MODEL="speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-onnx"
VOCOTYPE_VAD_MODEL="speech_fsmn_vad_zh-cn-16k-common-onnx"
VOCOTYPE_PUNC_MODEL="punc_ct-transformer_zh-cn-common-vocab272727-onnx"
SRC_URI="
https://github.com/LeonardNJU/VocoType-linux/archive/refs/tags/v${PV}.tar.gz
-> ${P}.tar.gz
https://modelscope.cn/models/iic/${VOCOTYPE_ASR_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/model_quant.onnx
-> vocotype-${VOCOTYPE_MODEL_REV}-asr-model_quant.onnx
https://modelscope.cn/models/iic/${VOCOTYPE_ASR_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/config.yaml
-> vocotype-${VOCOTYPE_MODEL_REV}-asr-config.yaml
https://modelscope.cn/models/iic/${VOCOTYPE_ASR_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/am.mvn
-> vocotype-${VOCOTYPE_MODEL_REV}-asr-am.mvn
https://modelscope.cn/models/iic/${VOCOTYPE_ASR_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/tokens.json
-> vocotype-${VOCOTYPE_MODEL_REV}-asr-tokens.json
https://modelscope.cn/models/iic/${VOCOTYPE_ASR_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/configuration.json
-> vocotype-${VOCOTYPE_MODEL_REV}-asr-configuration.json
https://modelscope.cn/models/iic/${VOCOTYPE_VAD_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/model_quant.onnx
-> vocotype-${VOCOTYPE_MODEL_REV}-vad-model_quant.onnx
https://modelscope.cn/models/iic/${VOCOTYPE_VAD_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/config.yaml
-> vocotype-${VOCOTYPE_MODEL_REV}-vad-config.yaml
https://modelscope.cn/models/iic/${VOCOTYPE_VAD_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/am.mvn
-> vocotype-${VOCOTYPE_MODEL_REV}-vad-am.mvn
https://modelscope.cn/models/iic/${VOCOTYPE_VAD_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/configuration.json
-> vocotype-${VOCOTYPE_MODEL_REV}-vad-configuration.json
https://modelscope.cn/models/iic/${VOCOTYPE_PUNC_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/model_quant.onnx
-> vocotype-${VOCOTYPE_MODEL_REV}-punc-model_quant.onnx
https://modelscope.cn/models/iic/${VOCOTYPE_PUNC_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/config.yaml
-> vocotype-${VOCOTYPE_MODEL_REV}-punc-config.yaml
https://modelscope.cn/models/iic/${VOCOTYPE_PUNC_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/tokens.json
-> vocotype-${VOCOTYPE_MODEL_REV}-punc-tokens.json
https://modelscope.cn/models/iic/${VOCOTYPE_PUNC_MODEL}/resolve/${VOCOTYPE_MODEL_REV}/configuration.json
-> vocotype-${VOCOTYPE_MODEL_REV}-punc-configuration.json
"
S="${WORKDIR}/VocoType-linux-${PV}"
LICENSE="GPL-3"
SLOT="0"
KEYWORDS="~amd64"
IUSE="+fcitx ibus +rime"
REQUIRED_USE="
|| ( ibus fcitx )
${PYTHON_REQUIRED_USE}
"
RDEPEND="
dev-python/sounddevice[${PYTHON_USEDEP}]
dev-python/librosa[${PYTHON_USEDEP}]
dev-python/soundfile[${PYTHON_USEDEP}]
dev-python/funasr-onnx[${PYTHON_USEDEP}]
dev-python/jieba[${PYTHON_USEDEP}]
ibus? (
app-i18n/ibus[python,${PYTHON_USEDEP}]
dev-python/pygobject[${PYTHON_USEDEP}]
)
fcitx? (
app-i18n/fcitx:5
)
rime? (
dev-python/pyrime[${PYTHON_USEDEP}]
app-i18n/librime
)
"
DEPEND="
fcitx? (
app-i18n/fcitx:5
dev-cpp/nlohmann_json
)
"
BDEPEND="
fcitx? (
dev-build/cmake
)
"
# Tests are post-install validation scripts requiring a deployed user
# environment ($HOME/.local/, running Rime), not suitable for ebuild sandbox
RESTRICT="test"
PATCHES=(
"${FILESDIR}/${P}-download-models.patch"
"${FILESDIR}/${P}-fcitx5-system-install.patch"
"${FILESDIR}/${P}-audio-fixes.patch"
)
src_prepare() {
default
# Fix deprecated project.license table format (PEP 639)
sed -i 's/^license = { file = "LICENSE" }/license = "GPL-3.0-or-later"/' pyproject.toml || die
# Fix IBus component XML paths for system-wide installation
if use ibus; then
sed -i \
-e "s|VOCOTYPE_EXEC_PATH|/usr/libexec/ibus-engine-vocotype|g" \
-e "s|VOCOTYPE_VERSION|${PV}|g" \
data/ibus/vocotype.xml.in || die
fi
# Copy rime_handler into app/ so it gets installed via distutils
if use fcitx; then
cp fcitx5/backend/rime_handler.py app/rime_handler.py || die
fi
}
src_configure() {
distutils-r1_src_configure
if use fcitx; then
local mycmakeargs=(
-DCMAKE_INSTALL_PREFIX="${EPREFIX}/usr"
-DCMAKE_INSTALL_LIBDIR="$(get_libdir)"
)
cmake -S "${S}/fcitx5/addon" -B "${S}/fcitx5/addon/build" \
"${mycmakeargs[@]}" || die "cmake configure failed"
fi
}
src_compile() {
distutils-r1_src_compile
if use fcitx; then
cmake --build "${S}/fcitx5/addon/build" -j$(makeopts_jobs) || die "cmake build failed"
fi
}
python_install() {
distutils-r1_python_install
# Per-implementation script installs
if use ibus; then
python_scriptinto /usr/libexec
python_newscript ibus/main.py ibus-engine-vocotype
fi
if use fcitx; then
python_scriptinto /usr/bin
python_newscript fcitx5/backend/fcitx5_server.py vocotype-fcitx5-backend
fi
# Audio device override wizard. Optional; default behaviour follows
# the system default input source without any conf file.
python_scriptinto /usr/bin
python_newscript scripts/setup-audio.py vocotype-setup-audio
}
src_install() {
distutils-r1_src_install
# IBus component
if use ibus; then
insinto /usr/share/ibus/component
newins data/ibus/vocotype.xml.in vocotype.xml
fi
# Fcitx5 addon
if use fcitx; then
# Install C++ addon shared library
exeinto "/usr/$(get_libdir)/fcitx5"
doexe "${S}/fcitx5/addon/build/vocotype.so"
# Install addon config
insinto /usr/share/fcitx5/addon
doins fcitx5/data/vocotype.conf
# Install input method config
insinto /usr/share/fcitx5/inputmethod
newins fcitx5/data/vocotype.conf.in vocotype.conf
# Install audio recorder script for C++ addon to invoke
insinto /usr/share/vocotype
doins fcitx5/backend/audio_recorder.py
# systemd user service (small file, install unconditionally per devmanual)
systemd_douserunit "${FILESDIR}/vocotype-fcitx5-backend.service"
# XDG autostart for the desktop session. The Exec= line defers to
# the systemd unit when available and falls back to running the
# binary directly, so a single backend starts in either setup.
insinto /etc/xdg/autostart
doins "${FILESDIR}/vocotype-fcitx5-backend.desktop"
fi
# Install pre-packaged models
local asr_files=( model_quant.onnx config.yaml am.mvn tokens.json configuration.json )
local vad_files=( model_quant.onnx config.yaml am.mvn configuration.json )
local punc_files=( model_quant.onnx config.yaml tokens.json configuration.json )
local f
insinto "/usr/share/vocotype/models/${VOCOTYPE_ASR_MODEL}"
for f in "${asr_files[@]}"; do
newins "${DISTDIR}/vocotype-${VOCOTYPE_MODEL_REV}-asr-${f}" "${f}"
done
insinto "/usr/share/vocotype/models/${VOCOTYPE_VAD_MODEL}"
for f in "${vad_files[@]}"; do
newins "${DISTDIR}/vocotype-${VOCOTYPE_MODEL_REV}-vad-${f}" "${f}"
done
insinto "/usr/share/vocotype/models/${VOCOTYPE_PUNC_MODEL}"
for f in "${punc_files[@]}"; do
newins "${DISTDIR}/vocotype-${VOCOTYPE_MODEL_REV}-punc-${f}" "${f}"
done
}
pkg_postinst() {
xdg_icon_cache_update
elog "VoCoType has been installed."
elog ""
if use ibus; then
elog "For IBus: restart ibus-daemon and add VoCoType in IBus settings."
elog " ibus restart"
elog ""
fi
if use fcitx; then
elog "For Fcitx5: the backend autostarts on the next desktop login."
elog "Then restart Fcitx5 to pick up the addon:"
elog " fcitx5 -r"
elog ""
fi
elog "VoCoType follows the system default input device on PipeWire/"
elog "PulseAudio. To inspect or change the active microphone:"
elog " wpctl status # list sources, default marked with *"
elog " pavucontrol # GUI: Recording / Input Devices tab"
elog "To pin a specific microphone, run: vocotype-setup-audio"
elog ""
elog "Usage: Press and hold F9 to speak, release to recognize."
}
pkg_postrm() {
xdg_icon_cache_update
}