diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa9e878..6d0e120 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,26 +2,33 @@ name: Package Application with Pyinstaller on: push: - branches: [master] + branches: [ master ] + tags: [ v* ] pull_request: - branches: [master] + branches: [ master ] jobs: build: runs-on: ubuntu-latest if: ${{ !contains(github.event.head_commit.message, '(deps') }} - steps: - uses: actions/checkout@v2 - uses: hmarr/debug-action@v2 - - name: Package Application for Windows + - name: Package CLI Application for Windows + uses: yshalsager/pyinstaller-action-windows@main + with: + path: . + spec: wit_transcriber.spec + requirements: requirements.txt + + - name: Package GUI Application for Windows uses: yshalsager/pyinstaller-action-windows@main with: path: . - spec: pyinstaller/wit_transcriber.spec - requirements: pyinstaller/requirements.txt + spec: wit_transcriber_gui.spec + requirements: requirements.txt - uses: actions/upload-artifact@v2 if: github.actor != 'dependabot[bot]' @@ -29,12 +36,26 @@ jobs: name: wit_transcriber.exe path: dist/windows - - name: Package Application for Linux + - uses: actions/upload-artifact@v2 + if: github.actor != 'dependabot[bot]' + with: + name: wit_transcriber_gui.exe + path: dist/windows + + - name: Package CLI Application for Linux uses: yshalsager/pyinstaller-action-linux@main with: path: . - spec: pyinstaller/wit_transcriber.spec - requirements: pyinstaller/requirements.txt + spec: wit_transcriber.spec + requirements: requirements.txt + + - name: Package GUI Application for Linux + uses: yshalsager/pyinstaller-action-linux@tkinter + with: + path: . + spec: wit_transcriber_gui.spec + requirements: requirements.txt + tkinter: true - uses: actions/upload-artifact@v2 if: github.actor != 'dependabot[bot]' @@ -42,16 +63,31 @@ jobs: name: wit_transcriber path: dist/linux - - name: Get datetime - id: datetime - run: echo ::set-output name=datetime::$(date +'%Y%m%d-%H%M%S') + - uses: actions/upload-artifact@v2 + if: github.actor != 'dependabot[bot]' + with: + name: wit_transcriber_gui + path: dist/linux + + - name: Set release name to tag name or datetime + id: release + run: | + echo ${{ github.ref }} + ref='refs/tags/v' + if [[ ${{ github.ref }} == *${ref}* ]]; then + echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + else + echo ::set-output name=version::$(date +'%Y%m%d-%H%M%S') + fi - name: Release - if: github.actor != 'dependabot[bot]' + if: github.actor != 'dependabot[bot]' && github.event_name != 'pull_request' uses: softprops/action-gh-release@v1 with: - tag_name: ${{ steps.datetime.outputs.datetime }} - name: ${{ steps.datetime.outputs.datetime }} + tag_name: ${{ steps.release.outputs.version }} + name: ${{ steps.release.outputs.version }} files: | dist/windows/wit_transcriber.exe dist/linux/wit_transcriber + dist/windows/wit_transcriber_gui.exe + dist/linux/wit_transcriber_gui diff --git a/.gitignore b/.gitignore index 0d2287d..84f3398 100644 --- a/.gitignore +++ b/.gitignore @@ -59,4 +59,5 @@ config.json *.txt *.mp* *.m4a -*.exe \ No newline at end of file +*.exe +last_run.log* \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d84568b..8f45f44 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: hooks: - id: system name: Requirements - entry: poetry export --format=requirements.txt --without-hashes --output=pyinstaller/requirements.txt + entry: poetry export --format=requirements.txt --without-hashes --output=requirements.txt pass_filenames: false language: system diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..488078d --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +pyinstaller-cli: + pyinstaller -F wit_transcriber/cli/app.py \ + --clean -y \ + --add-data="pyproject.toml:." \ + -n wit_transcriber +pyinstaller-gui: + pyinstaller -F wit_transcriber/gui/app.py \ + --clean -y \ + --add-data="pyproject.toml:." \ + --windowed \ + -n wit_transcriber_gui diff --git a/README.md b/README.md index d5ee0a3..d78c375 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,145 @@ # wit_transcriber + + A mini command line tool to transcribe media files using [wit.ai](https://wit.ai) + + [![GitHub release](https://img.shields.io/github/release/yshalsager/wit_transcriber.svg)](https://github.com/yshalsager/wit_transcriber/releases/) + + [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.png?v=103)](https://github.com/ellerbrock/open-source-badges/) + [![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/) + + [![PayPal](https://img.shields.io/badge/PayPal-Donate-00457C?style=flat&labelColor=00457C&logo=PayPal&logoColor=white&link=https://www.paypal.me/yshalsager)](https://www.paypal.me/yshalsager) + [![Patreon](https://img.shields.io/badge/Patreon-Support-F96854?style=flat&labelColor=F96854&logo=Patreon&logoColor=white&link=https://www.patreon.com/XiaomiFirmwareUpdater)](https://www.patreon.com/XiaomiFirmwareUpdater) + [![Liberapay](https://img.shields.io/badge/Liberapay-Support-F6C915?style=flat&labelColor=F6C915&logo=Liberapay&logoColor=white&link=https://liberapay.com/yshalsager)](https://liberapay.com/yshalsager) + + ## Configuring Wit.ai + + - Open [wit.ai](https://wit.ai/) and sign with Facebook account. + - Go to [wit.ai/apps](https://wit.ai/apps) and click on New App. + - Choose a name and select a language, set the app visibility to private, then press Create. + - Go to Management > Settings (`https://wit.ai/apps//settings`). + - Under the Client Access Token section click on the token to copy it, this is the API key. + + ## Usage + + **Note**: ffmpeg must be installed! + + Copy config example file to `config.json` and add required languages API keys you got from the previous step. + + ```bash + usage: wit_transcriber.py [-h] -i INPUT [-o OUTPUT] [-c CONFIG] [-x CONNECTIONS] [-l LANG] [-v] + + options: - -h, --help show this help message and exit - -i INPUT, --input INPUT - Path of media file to be transcribed. - -o OUTPUT, --output OUTPUT - Path of output file. - -c CONFIG, --config CONFIG - Path of config file. - -x CONNECTIONS, --connections CONNECTIONS - Number of API connections limit. - -l LANG, --lang LANG Language to use. - -v, --verbose Print API responses. + +-h, --help show this help message and exit + +-i INPUT, --input INPUT + +Path of media file to be transcribed. + +-o OUTPUT, --output OUTPUT + +Path of output file. + +-c CONFIG, --config CONFIG + +Path of config file. + +-x CONNECTIONS, --connections CONNECTIONS + +Number of API connections limit. + +-l LANG, --lang LANG Language to use. + +-v, --verbose Print API responses. + ``` + + --- + + # أداة التفريغ النصي بواسطة wit.ai + + أداة صغيرة لتفريغ الصوتيات عبر [wit.ai](https://wit.ai). + + ## إعداد Wit.ai + + - افتح [wit.ai](https://wit.ai/) وسجل الدخول بحساب فيس بوك. + - افتح [wit.ai/apps](https://wit.ai/apps) واضغط على New App لإنشاء تطبيق جديد. + - اختر اسمًا للتطبيق واختر لغةَ ثم عدل إعدادات ظهور التطبيق إلى خاص واضغط إنشاء. + - افتح قسم اﻹدارة ثم اﻹعدادات Management > Settings (`https://wit.ai/apps//settings`). + - أسفل قسم Client Access Token section ستجد مفتاح استخدام الواجهة البرمجية، انسخه لتستخدمه في الخطوة التالية. + + ## الاستخدام + + انسخ ملف config example إلى ملف باسم `config.json` ثم أضف مفاتيح استخدام الواجهة البرمجية الخاصة باللغات المطلوبة. + + ### تشغيل اﻷداة على ويندوز +#### من خلال الواجهة الرسومية + يمكن تحميل الاداة بواجهة رسومية [من هنا](/release/TranscribeArabic_v1.0.0.zip) +![main_window](/screenshots/1.png) + ثم اضافة مفتاح التشغيل الخاص بموقع wit.at من خلال شاشة الاعدادات كالتالي: + ![settings_window](/screenshots/2.png) + + +#### من خلال اوامر التشغيل CMD + - حمل أحدث نسخة من الملف التنفيذي للأداة من [هنا](https://github.com/yshalsager/wit_transcriber/releases/latest). + - حمل ملفات ffmpeg إذا لم يكن مثبتا عندك من [هنا](https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.7z) وفك الضغط عن الملف ثم انقل `ffmpeg.exe` و `ffprobe.exe` إلى نفس المجلد الذي به الأداة. -- شغل الملف التنفيذي عبر سطر/موجه اﻷوامر مع استبدال كلمة filename باسم الملف المراد تفريغه. +- شغل الملف التنفيذي عبر سطر/موجه اﻷوامر مع استبدال كلمة filename باسم الملف المراد تفريغه. ```powershell + ./wit_transcriber.exe -i filename + ``` diff --git a/main.ico b/main.ico new file mode 100644 index 0000000..b782eef Binary files /dev/null and b/main.ico differ diff --git a/poetry.lock b/poetry.lock index 64b5534..625a22f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -23,6 +23,18 @@ doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] trio = ["trio (>=0.16)"] +[[package]] +name = "awesometkinter" +version = "2021.11.8" +description = "Pretty tkinter widgets" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pillow = ">=6.0.0" +python-bidi = "*" + [[package]] name = "black" version = "22.6.0" @@ -62,26 +74,26 @@ python-versions = ">=3.6.1" [[package]] name = "click" -version = "8.0.4" +version = "8.1.3" description = "Composable command line interface toolkit" -category = "dev" +category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.5" description = "Cross-platform colored terminal text." -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "distlib" -version = "0.3.4" +version = "0.3.5" description = "Distribution utilities" category = "dev" optional = false @@ -89,7 +101,7 @@ python-versions = "*" [[package]] name = "filelock" -version = "3.6.0" +version = "3.7.1" description = "A platform independent file lock." category = "dev" optional = false @@ -168,7 +180,7 @@ socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "identify" -version = "2.4.11" +version = "2.5.3" description = "File identification library for Python" category = "dev" optional = false @@ -201,7 +213,7 @@ plugins = ["setuptools"] [[package]] name = "macholib" -version = "1.15.2" +version = "1.16" description = "Mach-O header analysis and editing" category = "dev" optional = false @@ -246,11 +258,11 @@ python-versions = "*" [[package]] name = "nodeenv" -version = "1.6.0" +version = "1.7.0" description = "Node.js virtual environment builder" category = "dev" optional = false -python-versions = "*" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" [[package]] name = "pathspec" @@ -271,17 +283,29 @@ python-versions = ">=3.6.0" [package.dependencies] future = "*" +[[package]] +name = "pillow" +version = "9.2.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + [[package]] name = "platformdirs" -version = "2.5.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pre-commit" @@ -344,12 +368,23 @@ hook_testing = ["pytest (>=2.7.3)", "execnet (>=1.5.0)", "psutil"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2022.2" +version = "2022.8" description = "Community maintained hooks for PyInstaller" category = "dev" optional = false python-versions = ">=3.7" +[[package]] +name = "python-bidi" +version = "0.4.2" +description = "Pure python implementation of the BiDi layout algorithm" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + [[package]] name = "pywin32-ctypes" version = "0.2.0" @@ -395,7 +430,7 @@ idna2008 = ["idna"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" @@ -411,48 +446,47 @@ python-versions = ">=3.5" name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.2.3" +version = "2.0.1" description = "A lil' TOML parser" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.3.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "virtualenv" -version = "20.13.2" +version = "20.16.3" description = "Virtual Python Environment builder" category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.6" [package.dependencies] -distlib = ">=0.3.1,<1" -filelock = ">=3.2,<4" -platformdirs = ">=2,<3" -six = ">=1.9.0,<2" +distlib = ">=0.3.5,<1" +filelock = ">=3.4.1,<4" +platformdirs = ">=2.4,<3" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] +docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] +testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] [metadata] lock-version = "1.1" python-versions = ">=3.10,<3.11" -content-hash = "c6900b68aaac8302c3391345c2a6342ac0d68cce6c1b99bbab5ee466a09fcb9b" +content-hash = "d98c2349403beaa533b5a0a1dfc58cd58671f78536c616779f85f230cc61afa3" [metadata.files] altgraph = [ @@ -463,6 +497,10 @@ anyio = [ {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"}, {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"}, ] +awesometkinter = [ + {file = "AwesomeTkinter-2021.11.8-py3-none-any.whl", hash = "sha256:a10aa984d7d60e90e3c76e96698d3f0377aeb14461d83d824d8096b5e0c55950"}, + {file = "AwesomeTkinter-2021.11.8.tar.gz", hash = "sha256:2944e11468a437d51859f596b755c64f0df557b92b7641626fe3cfb222e4c180"}, +] black = [ {file = "black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"}, {file = "black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"}, @@ -497,20 +535,20 @@ cfgv = [ {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] click = [ - {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, - {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] distlib = [ - {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, - {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, + {file = "distlib-0.3.5-py2.py3-none-any.whl", hash = "sha256:b710088c59f06338ca514800ad795a132da19fda270e3ce4affc74abf955a26c"}, + {file = "distlib-0.3.5.tar.gz", hash = "sha256:a7f75737c70be3b25e2bee06288cec4e4c221de18455b2dd037fe2a795cab2fe"}, ] filelock = [ - {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, - {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, + {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"}, + {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"}, ] flake8 = [ {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, @@ -532,8 +570,8 @@ httpx = [ {file = "httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"}, ] identify = [ - {file = "identify-2.4.11-py2.py3-none-any.whl", hash = "sha256:fd906823ed1db23c7a48f9b176a1d71cb8abede1e21ebe614bac7bdd688d9213"}, - {file = "identify-2.4.11.tar.gz", hash = "sha256:2986942d3974c8f2e5019a190523b0b0e2a07cb8e89bf236727fb4b26f27f8fd"}, + {file = "identify-2.5.3-py2.py3-none-any.whl", hash = "sha256:25851c8c1370effb22aaa3c987b30449e9ff0cece408f810ae6ce408fdd20893"}, + {file = "identify-2.5.3.tar.gz", hash = "sha256:887e7b91a1be152b0d46bbf072130235a8117392b9f1828446079a816a05ef44"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, @@ -544,8 +582,8 @@ isort = [ {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] macholib = [ - {file = "macholib-1.15.2-py2.py3-none-any.whl", hash = "sha256:885613dd02d3e26dbd2b541eb4cc4ce611b841f827c0958ab98656e478b9e6f6"}, - {file = "macholib-1.15.2.tar.gz", hash = "sha256:1542c41da3600509f91c165cb897e7e54c0e74008bd8da5da7ebbee519d593d2"}, + {file = "macholib-1.16-py2.py3-none-any.whl", hash = "sha256:5a0742b587e6e57bfade1ab90651d4877185bf66fd4a176a488116de36878229"}, + {file = "macholib-1.16.tar.gz", hash = "sha256:001bf281279b986a66d7821790d734e61150d52f40c080899df8fefae056e9f7"}, ] mccabe = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, @@ -581,8 +619,8 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] nodeenv = [ - {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, - {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, ] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, @@ -591,9 +629,69 @@ pathspec = [ pefile = [ {file = "pefile-2022.5.30.tar.gz", hash = "sha256:a5488a3dd1fd021ce33f969780b88fe0f7eebb76eb20996d7318f307612a045b"}, ] +pillow = [ + {file = "Pillow-9.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb"}, + {file = "Pillow-9.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f"}, + {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5"}, + {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c"}, + {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1"}, + {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58"}, + {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544"}, + {file = "Pillow-9.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e"}, + {file = "Pillow-9.2.0-cp310-cp310-win32.whl", hash = "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28"}, + {file = "Pillow-9.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d"}, + {file = "Pillow-9.2.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8"}, + {file = "Pillow-9.2.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9"}, + {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004"}, + {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0"}, + {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4"}, + {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c"}, + {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a"}, + {file = "Pillow-9.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1"}, + {file = "Pillow-9.2.0-cp311-cp311-win32.whl", hash = "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf"}, + {file = "Pillow-9.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c"}, + {file = "Pillow-9.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069"}, + {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f"}, + {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8"}, + {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b"}, + {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467"}, + {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59"}, + {file = "Pillow-9.2.0-cp37-cp37m-win32.whl", hash = "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc"}, + {file = "Pillow-9.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d"}, + {file = "Pillow-9.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14"}, + {file = "Pillow-9.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3"}, + {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402"}, + {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f"}, + {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8"}, + {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff"}, + {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1"}, + {file = "Pillow-9.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76"}, + {file = "Pillow-9.2.0-cp38-cp38-win32.whl", hash = "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f"}, + {file = "Pillow-9.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8"}, + {file = "Pillow-9.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc"}, + {file = "Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da"}, + {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4"}, + {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c"}, + {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421"}, + {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20"}, + {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60"}, + {file = "Pillow-9.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4"}, + {file = "Pillow-9.2.0-cp39-cp39-win32.whl", hash = "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885"}, + {file = "Pillow-9.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4"}, + {file = "Pillow-9.2.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3"}, + {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb"}, + {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be"}, + {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd"}, + {file = "Pillow-9.2.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013"}, + {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490"}, + {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac"}, + {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e"}, + {file = "Pillow-9.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927"}, + {file = "Pillow-9.2.0.tar.gz", hash = "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04"}, +] platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pre-commit = [ {file = "pre_commit-2.20.0-py2.py3-none-any.whl", hash = "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7"}, @@ -625,8 +723,12 @@ pyinstaller = [ {file = "pyinstaller-5.3.tar.gz", hash = "sha256:de71d4669806e4d54b23b477cc077e2e8fe9c4d57e79ed32d22b7585137fd7b7"}, ] pyinstaller-hooks-contrib = [ - {file = "pyinstaller-hooks-contrib-2022.2.tar.gz", hash = "sha256:ab1d14fe053016fff7b0c6aea51d980bac6d02114b04063b46ef7dac70c70e1e"}, - {file = "pyinstaller_hooks_contrib-2022.2-py2.py3-none-any.whl", hash = "sha256:7605e440ccb55904cb2a87d72e83642ef176fb7030c77e52ac4d9679bb3d1537"}, + {file = "pyinstaller-hooks-contrib-2022.8.tar.gz", hash = "sha256:c4210fc50282c9c6a918e485e0bfae9405592390508e3be9fde19acc2213da56"}, + {file = "pyinstaller_hooks_contrib-2022.8-py2.py3-none-any.whl", hash = "sha256:e46f099934dd4577fb1ddcf37a99fa04027c92f8f5291c8802f326345988d001"}, +] +python-bidi = [ + {file = "python-bidi-0.4.2.tar.gz", hash = "sha256:5347f71e82b3e9976dc657f09ded2bfe39ba8d6777ca81a5b2c56c30121c496e"}, + {file = "python_bidi-0.4.2-py2.py3-none-any.whl", hash = "sha256:50eef6f6a0bbdd685f9e8c207f3c9050f5b578d0a46e37c76a9c4baea2cc2e13"}, ] pywin32-ctypes = [ {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, @@ -688,14 +790,14 @@ toml = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ - {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, - {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, + {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, ] virtualenv = [ - {file = "virtualenv-20.13.2-py2.py3-none-any.whl", hash = "sha256:e7b34c9474e6476ee208c43a4d9ac1510b041c68347eabfe9a9ea0c86aa0a46b"}, - {file = "virtualenv-20.13.2.tar.gz", hash = "sha256:01f5f80744d24a3743ce61858123488e91cb2dd1d3bdf92adaf1bba39ffdedf0"}, + {file = "virtualenv-20.16.3-py2.py3-none-any.whl", hash = "sha256:4193b7bc8a6cd23e4eb251ac64f29b4398ab2c233531e66e40b19a6b7b0d30c1"}, + {file = "virtualenv-20.16.3.tar.gz", hash = "sha256:d86ea0bb50e06252d79e6c241507cb904fcd66090c3271381372d6221a3970f9"}, ] diff --git a/pyinstaller/requirements.txt b/pyinstaller/requirements.txt deleted file mode 100644 index 713c004..0000000 --- a/pyinstaller/requirements.txt +++ /dev/null @@ -1,11 +0,0 @@ -anyio==3.6.1; python_full_version >= "3.6.2" and python_version >= "3.6" -certifi==2022.6.15; python_version >= "3.6" -charset-normalizer==2.1.0; python_full_version >= "3.5.0" and python_version >= "3.6" -h11==0.12.0; python_version >= "3.6" -httpcore==0.15.0; python_version >= "3.6" -httpx==0.23.0; python_version >= "3.6" -idna==3.3; python_version >= "3.6" and python_full_version >= "3.6.2" -pydub==0.25.1 -ratelimiter==1.2.0.post0 -rfc3986==1.5.0; python_version >= "3.6" -sniffio==1.2.0; python_full_version >= "3.6.2" and python_version >= "3.6" diff --git a/pyproject.toml b/pyproject.toml index 4b30d59..e2db0d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "wit_transcriber" -version = "0.1.0" -description = "A mini command line tool to transcribe media files using wit.ai" +version = "0.2.0" +description = "A tool to transcribe media files using wit.ai" authors = ["yshalsager "] [tool.poetry.dependencies] @@ -9,6 +9,9 @@ python = ">=3.10,<3.11" httpx = "^0.23.0" pydub = "^0.25.1" ratelimiter = "^1.2.0" +AwesomeTkinter = {version = "^2021.11.8", extras = ["gui"]} +click = "^8.1.3" +toml = "^0.10.2" [tool.poetry.dev-dependencies] black = "^22.6" @@ -23,11 +26,12 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] -wit_transcriber = 'wit_transcriber:main' +wit_transcriber = 'wit_transcriber.cli.app:transcribe' +wit_transcriber_gui = 'wit_transcriber.gui.app:gui' [tool.black] -include = '(droos_bot\/.*$|\.pyi?$)' +include = '(wit_transcriber\/.*$|\.pyi?$)' exclude = ''' /( \.git @@ -40,7 +44,7 @@ exclude = ''' profile = "black" [tool.mypy] -files = ["droos_bot"] +files = ["wit_transcriber"] ignore_missing_imports = true disallow_untyped_defs = true #disallow_any_unimported = true diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ec33aad --- /dev/null +++ b/requirements.txt @@ -0,0 +1,17 @@ +anyio==3.6.1; python_full_version >= "3.6.2" and python_version >= "3.7" +awesometkinter==2021.11.8; python_version >= "3.6" +certifi==2022.6.15; python_version >= "3.7" +click==8.1.3; python_version >= "3.7" +colorama==0.4.5; python_version >= "3.7" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.7" and python_full_version >= "3.5.0" +h11==0.12.0; python_version >= "3.7" +httpcore==0.15.0; python_version >= "3.7" +httpx==0.23.0; python_version >= "3.7" +idna==3.3; python_version >= "3.7" and python_full_version >= "3.6.2" +pillow==9.2.0; python_version >= "3.7" +pydub==0.25.1 +python-bidi==0.4.2; python_version >= "3.6" +ratelimiter==1.2.0.post0 +rfc3986==1.5.0; python_version >= "3.7" +six==1.16.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" +sniffio==1.2.0; python_full_version >= "3.6.2" and python_version >= "3.7" +toml==0.10.2; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") diff --git a/screenshots/1.png b/screenshots/1.png new file mode 100644 index 0000000..f366019 Binary files /dev/null and b/screenshots/1.png differ diff --git a/screenshots/2.png b/screenshots/2.png new file mode 100644 index 0000000..6ff53a0 Binary files /dev/null and b/screenshots/2.png differ diff --git a/screenshots/3.png b/screenshots/3.png new file mode 100644 index 0000000..c71b2a0 Binary files /dev/null and b/screenshots/3.png differ diff --git a/screenshots/4.png b/screenshots/4.png new file mode 100644 index 0000000..4b39db1 Binary files /dev/null and b/screenshots/4.png differ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3e6ff9e --- /dev/null +++ b/setup.py @@ -0,0 +1,66 @@ +import os +import shutil +import sys + +import cx_Freeze + +os.environ["TCL_LIBRARY"] = r"PATH_TO_PYTHON\\tcl\\tcl8.6" +os.environ["TK_LIBRARY"] = r"PATH_TO_PYTHON\\tcl\\tk8.6" + +__version__ = "1.0.0" +base = None +if sys.platform == "win32": + base = "Win32GUI" + +include_files = ["ffmpeg.exe", "main.ico"] +includes = ["tkinter"] +excludes = ["matplotlib", "sqlite3"] +packages = [ + "httpx", + "http", + "anyio", + "traceback", + "pydub", + "asyncio", + "traceback", + "json", + "re", + "typing", + "pathlib", + "ratelimiter", + "distutils", +] + +cx_Freeze.setup( + name="Transcribe Arabic", + description="تحويل الملفات الصوتية الي نصوص", + version=__version__, + executables=[ + cx_Freeze.Executable( + "wit_transcriber/gui/main_window.py", + base=base, + icon="main.ico", + shortcutName="Transcribe Arabic", + shortcutDir="DesktopFolder", + ) + ], + options={ + "build_exe": { + "packages": packages, + "includes": includes, + "include_files": include_files, + "include_msvcr": True, + "excludes": excludes, + }, + "bdist_msi": { + "upgrade_code": "{00EF338F-794D-3AB8-8CD6-2B0AB7541021}", + "add_to_path": False, + "initial_target_dir": r"[ProgramFilesFolder]\%s" % ("TranscribeArabic"), + }, + }, +) + +path = os.path.abspath(os.path.join(os.path.realpath(__file__), os.pardir)) +build_path = os.path.join(path, "build", "exe.win32-3.7") +shutil.copy(r"PATH_TO_PYTHON\\DLLs\\tcl86t.dll", build_path) +shutil.copy(r"PATH_TO_PYTHON\\DLLs\\tk86t.dll", build_path) diff --git a/pyinstaller/wit_transcriber.spec b/wit_transcriber.spec similarity index 89% rename from pyinstaller/wit_transcriber.spec rename to wit_transcriber.spec index 852ae73..5a9a451 100644 --- a/pyinstaller/wit_transcriber.spec +++ b/wit_transcriber.spec @@ -5,13 +5,13 @@ block_cipher = None a = Analysis( - ['../wit_transcriber.py'], + ['wit_transcriber/cli/app.py'], pathex=[], binaries=[], - datas=[], + datas=[('pyproject.toml', '.')], hiddenimports=[], hookspath=[], - hooksconfig=None, + hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, diff --git a/wit_transcriber/__init__.py b/wit_transcriber/__init__.py new file mode 100644 index 0000000..03ca00b --- /dev/null +++ b/wit_transcriber/__init__.py @@ -0,0 +1,43 @@ +"""Module initialization""" +import logging +from importlib import metadata +from logging.handlers import TimedRotatingFileHandler +from pathlib import Path +from sys import stderr, stdout + +import toml + +# Use __file__ so PyInstaller bundle can access files too +PKG_DIR = Path(__file__).absolute().parent +PARENT_DIR = PKG_DIR.parent + +# Set package version dynamically +try: + # In production use package metadata + __version__ = metadata.version(__package__) +except metadata.PackageNotFoundError: + # otherwise, read version from pyproject + + __version__ = toml.loads((PARENT_DIR / "pyproject.toml").read_text())["tool"][ + "poetry" + ]["version"] + + +CONFIG_FILE = PARENT_DIR / "config.json" +# Logging +LOG_FILE = PARENT_DIR / "last_run.log" +LOG_FORMAT = "%(asctime)s [%(levelname)s] %(name)s [%(module)s.%(funcName)s:%(lineno)d]: %(message)s" +FORMATTER: logging.Formatter = logging.Formatter(LOG_FORMAT) +handler = TimedRotatingFileHandler(LOG_FILE, when="d", interval=1, backupCount=3) +logging.basicConfig(filename=str(LOG_FILE), filemode="w", format=LOG_FORMAT) +OUT = logging.StreamHandler(stdout) +ERR = logging.StreamHandler(stderr) +OUT.setFormatter(FORMATTER) +ERR.setFormatter(FORMATTER) +OUT.setLevel(logging.INFO) +ERR.setLevel(logging.WARNING) +LOGGER = logging.getLogger() +LOGGER.addHandler(OUT) +LOGGER.addHandler(ERR) +LOGGER.addHandler(handler) +LOGGER.setLevel(logging.INFO) diff --git a/wit_transcriber/__main__.py b/wit_transcriber/__main__.py new file mode 100644 index 0000000..bf4c623 --- /dev/null +++ b/wit_transcriber/__main__.py @@ -0,0 +1,20 @@ +"""Entry Point.""" +import click + +from wit_transcriber.cli.app import transcribe +from wit_transcriber.gui.app import gui + + +@click.group() +def click_cli() -> None: + pass + + +def main() -> None: + click_cli.add_command(transcribe) + click_cli.add_command(gui) + click_cli() + + +if __name__ == "__main__": + main() diff --git a/wit_transcriber/api_client/__init__.py b/wit_transcriber/api_client/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wit_transcriber.py b/wit_transcriber/api_client/client.py similarity index 71% rename from wit_transcriber.py rename to wit_transcriber/api_client/client.py index 4e5e32c..9f9d0e2 100644 --- a/wit_transcriber.py +++ b/wit_transcriber/api_client/client.py @@ -1,8 +1,7 @@ import json import re import traceback -from argparse import ArgumentParser -from asyncio import BoundedSemaphore, ensure_future, gather, run +from asyncio import BoundedSemaphore, ensure_future, gather from pathlib import Path from typing import List, Tuple @@ -46,7 +45,7 @@ def text(self) -> str: ) # strip extra white spaces from lines text = text.replace(".", ".\n").replace("\n ", "\n") - text = re.sub("[ ]{2,}", " ", text, re.M) + text = re.sub(" {2,}", " ", text, re.M) return text def has_api_key(self) -> bool: @@ -117,7 +116,7 @@ async def __preprocess_audio(audio: AudioSegment) -> AudioSegment: return audio.set_sample_width(2).set_channels(1).set_frame_rate(8000) async def __bound_fetch(self, chunk: AudioSegment, idx: int) -> Tuple[str, str]: - # Getter function with semaphore. + # Getter functions with semaphore. async with self._sem: return await self.__transcribe_chunk(chunk, idx) @@ -146,76 +145,3 @@ async def transcribe(self, path: Path) -> None: raise Exception( "`Error decoding the audio file.\nEnsure that the provided audio is a valid audio file!`" ) - - -async def transcribe( - file_path: Path, - output: Path, - semaphore: int, - config_file: Path, - verbose: bool = False, - lang: str = "ar", -) -> None: - """Speech to text using Wit.ai""" - api = WitAiAPI(lang, semaphore, config_file, verbose=verbose) - if not api.has_api_key(): - raise RuntimeError("Language API key was not found! Exitting!") - await api.transcribe(file_path) - Path(output).write_text(api.text, encoding="utf-8") - - -def main() -> None: - parser = ArgumentParser() - parser.add_argument( - "-i", - "--input", - help="Path of media file to be transcribed.", - required=True, - type=Path, - ) - parser.add_argument("-o", "--output", help="Path of output file.", type=Path) - parser.add_argument( - "-c", - "--config", - help="Path of config file.", - type=Path, - default=Path("config.json"), - ) - parser.add_argument( - "-x", - "--connections", - help="Number of API connections limit.", - type=int, - default=5, - ) - parser.add_argument( - "-l", - "--lang", - help="Language to use.", - type=str, - default="ar", - ) - parser.add_argument( - "-v", "--verbose", action="store_true", help="Print API responses." - ) - args = parser.parse_args() - if not args.input.exists(): - raise RuntimeError("Input file doesn't exist! Exitting!") - if not args.config.exists(): - raise RuntimeError("Config was not found! Exitting!") - - output_file = args.output if args.output else Path(f"{args.input.stem}.txt") - run( - transcribe( - args.input, - output_file, - args.connections, - args.config, - verbose=args.verbose, - lang=args.lang, - ) - ) - - -if __name__ == "__main__": - main() diff --git a/wit_transcriber/cli/__init__.py b/wit_transcriber/cli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wit_transcriber/cli/app.py b/wit_transcriber/cli/app.py new file mode 100644 index 0000000..f11fea4 --- /dev/null +++ b/wit_transcriber/cli/app.py @@ -0,0 +1,74 @@ +from asyncio import run +from pathlib import Path + +import click + +from wit_transcriber import CONFIG_FILE +from wit_transcriber.api_client.client import WitAiAPI + + +@click.command() +@click.option( + "-i", + "--input", + "file_path", + type=Path, + help="Path of media file to be transcribed.", + required=True, +) +@click.option("-o", "--output", type=Path, help="Path of output file.") +@click.option( + "-c", + "--config", + "config_file", + type=Path, + help="Path of config file.", + default=CONFIG_FILE, +) +@click.option( + "-x", "--connections", type=int, help="Number of API connections limit.", default=5 +) +@click.option("-l", "--lang", type=str, help="Language to use.", default="ar") +@click.option("-v", "--verbose", type=bool, help="Print API responses.", default=False) +def transcribe( + file_path: Path, + output: Path, + connections: int, + config_file: Path, + verbose: bool = False, + lang: str = "ar", +) -> None: + run(run_transcribe(file_path, output, connections, config_file, verbose, lang)) + + +async def run_transcribe( + file_path: Path, + output: Path, + connections: int, + config_file: Path, + verbose: bool, + lang: str, +) -> None: + """Speech to text using Wit.ai""" + if not file_path.exists(): + raise RuntimeError("Input file doesn't exist! Exiting!") + if not config_file.exists(): + raise RuntimeError("Config was not found! Exiting!") + output_file = output if output else Path(f"{file_path.stem}.txt") + + api_client = WitAiAPI(lang, connections, config_file, verbose=verbose) + if not api_client.has_api_key(): + raise RuntimeError("Language API key was not found! Exiting!") + await api_client.transcribe(file_path) + Path(output_file).write_text(api_client.text, encoding="utf-8") + print("Done Successfully!") + + +if __name__ == "__main__": + + @click.group() + def cli() -> None: + pass + + cli.add_command(transcribe) + transcribe() diff --git a/wit_transcriber/gui/__init__.py b/wit_transcriber/gui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wit_transcriber/gui/app.py b/wit_transcriber/gui/app.py new file mode 100644 index 0000000..b458093 --- /dev/null +++ b/wit_transcriber/gui/app.py @@ -0,0 +1,20 @@ +from asyncio import run + +import click + +from wit_transcriber.gui.main_window import App + + +@click.command() +def gui() -> None: + run(App().exec()) + + +if __name__ == "__main__": + + @click.group() + def cli() -> None: + pass + + cli.add_command(gui) + gui() diff --git a/wit_transcriber/gui/constants.py b/wit_transcriber/gui/constants.py new file mode 100644 index 0000000..b7c91b5 --- /dev/null +++ b/wit_transcriber/gui/constants.py @@ -0,0 +1,11 @@ +OUTPUT_BUTTON_TITLE = "تغيير مجلد الحفظ" +INPUT_BUTTON_TITLE = "اختيار الملف" +INPUT_DIALOG_TITLE = "اختيار الملف الصوتي" +SUBMIT_BUTTON = " بدء التحويل" +MENU_BAR_FILE = "ملف" +MENU_BAR_FILE_SETTINGS = "الإعدادات" +MENU_BAR_FILE_NEW = "ملف جديد" +MENU_BAR_FILE_EXIT = "خروج" +MENU_BAR_HELP = "مساعدة" +MENU_BAR_ABOUT = "حول البرنامج" +ERROR_API_KEY = "برجاء إضافة المفتاح الخاص بموقع wit.ai وإعادة المحاولة" diff --git a/wit_transcriber/gui/main_window.py b/wit_transcriber/gui/main_window.py new file mode 100644 index 0000000..37b5169 --- /dev/null +++ b/wit_transcriber/gui/main_window.py @@ -0,0 +1,217 @@ +import sys +import tkinter as tk +import tkinter.font as tkFont +from asyncio import create_task, get_event_loop, sleep +from pathlib import Path +from platform import system +from tkinter import StringVar, filedialog, messagebox +from webbrowser import open_new_tab + +from wit_transcriber import PARENT_DIR +from wit_transcriber.api_client.client import WitAiAPI +from wit_transcriber.gui import constants +from wit_transcriber.gui.preferences import PreferencesManager +from wit_transcriber.gui.settings import SettingWindow +from wit_transcriber.gui.utils import _text + + +class IORedirector: + # https://stackoverflow.com/a/3333386 + """A general class for redirecting I/O to this Text widget.""" + + def __init__(self, text_area: tk.Text) -> None: + self.text_area = text_area + + +class StdoutRedirector(IORedirector): + """A class for redirecting stdout to this Text widget.""" + + def __init__(self, text_area: tk.Text): + super().__init__(text_area) + + def write(self, string: str) -> None: + self.text_area.insert("end", _text(system(), string)) + self.text_area.see("end") + + def flush(self) -> None: + pass + + +""" +Idea for connecting asyncio loop_event with tkinter main_loop from: +https://www.loekvandenouweland.com/content/python-asyncio-and-tkinter.html +""" + + +class App: + def __init__(self) -> None: + self._platform = system() + self.parent: tk.Tk = tk.Tk() + self.parent.protocol("WM_DELETE_WINDOW", self.on_closing) + self.parent.title("أداة التفريغ الصوتي") + # self.parent.iconphoto(True, tk.PhotoImage(file=str(PARENT_DIR / "chat-centered-text-duotone.png"))) + self.output_path = StringVar() + self.input_path = StringVar() + self.init_settings() + self.preference = PreferencesManager(Path().absolute()) + self.default_font = tkFont.nametofont("TkDefaultFont") + self.default_font.configure(family="Tajawal", size=10) + + self.menu = tk.Menu(self.parent) + self.label = tk.Label( + self.parent, text=self.render_text("wit.ai أداة للتفريغ الصوتي باستخدام") + ) + self.input_entry = tk.Entry(self.parent, textvariable=self.input_path, width=60) + self.output_entry = tk.Entry( + self.parent, textvariable=self.output_path, width=60 + ) + self.startTranscribe = tk.Button( + self.parent, + text=self.render_text(constants.SUBMIT_BUTTON), + command=lambda: create_task(self.get_transcribe()), + ) + self.scrollbar = tk.Scrollbar(self.parent, orient=tk.VERTICAL) + self.output_area = tk.Text( + self.parent, + height=5, + width=25, + bg="light gray", + yscrollcommand=self.scrollbar.set, + ) + self.verbose_checkbox_var = tk.IntVar() + self.init_ui() + + def init_settings(self) -> None: + self.output_path.set(str(Path().absolute())) + + def init_ui(self) -> None: + file_menu = tk.Menu(self.menu, tearoff=0) + file_menu.add_command( + label=self.render_text(constants.MENU_BAR_FILE_NEW), + command=self.ask_for_input_path, + ) + file_menu.add_command( + label=self.render_text(constants.MENU_BAR_FILE_SETTINGS), + command=self.open_win, + ) + file_menu.add_separator() + file_menu.add_command( + label=self.render_text(constants.MENU_BAR_FILE_EXIT), + command=self.on_closing, + ) + help_menu = tk.Menu(self.menu, tearoff=0) + help_menu.add_command( + label=self.render_text(constants.MENU_BAR_ABOUT), + command=lambda: open_new_tab( + "https://github.com/yshalsager/wit_transcriber" + ), + ) + self.menu.add_cascade( + label=self.render_text(constants.MENU_BAR_FILE), menu=file_menu + ) + self.menu.add_cascade( + label=self.render_text(constants.MENU_BAR_HELP), menu=help_menu + ) + self.parent.config(menu=self.menu) + + self.label.grid(row=0, column=0, pady=10, sticky="w,e") + self.input_entry.grid(row=1, column=0, pady=10, padx=10) + self.output_entry.grid(row=3, column=0, pady=10, padx=10) + + tk.Button( + self.parent, + text=self.render_text(constants.INPUT_BUTTON_TITLE), + command=self.ask_for_input_path, + ).grid(row=1, column=1, pady=10, padx=10) + + tk.Button( + self.parent, + text=self.render_text(constants.OUTPUT_BUTTON_TITLE), + command=self.ask_for_output_path, + ).grid(row=3, column=1, pady=10, padx=10) + + self.startTranscribe.grid(row=4, column=0, pady=10, padx=10, columnspan=2) + + self.scrollbar.config(command=self.output_area.yview) + self.output_area.grid(row=5, column=0, sticky="wes", padx=10, pady=10) + self.scrollbar.grid(row=5, column=0, sticky="nse", padx=10, pady=10) + + sys.stdout = StdoutRedirector(self.output_area) # type: ignore + + # print(self.verbose_checkbox_var) + verbose_checkbox = tk.Checkbutton( + self.parent, + variable=self.verbose_checkbox_var, + justify="center", + text=self.render_text("إظهار النتائج"), + offvalue=0, + onvalue=1, + ) + verbose_checkbox.grid(row=6, column=0, sticky="w", padx=10, pady=10) + + # TODO [Improvement] edit to handle onClosing and stop asyncio loop + async def show(self) -> None: + while True: + self.parent.update() + await sleep(0.1) + + def ask_for_output_path(self) -> None: + output_path = filedialog.askdirectory() + self.output_path.set(output_path) + + def ask_for_input_path(self) -> None: + input_path = filedialog.askopenfilename( + initialdir="/", + title=self.render_text(constants.INPUT_DIALOG_TITLE), + filetypes=( + ("Audio files", "*.mp3 *.wav *.m4a *.ogg"), + ("all files", "*.*"), + ), + ) + self.input_path.set(input_path) + + def on_error_occurs(self, error_msg: str) -> None: + messagebox.showerror(self.render_text("خطأ"), error_msg) + + def open_win(self) -> None: + SettingWindow(self.parent, self.preference, self.render_text) + + def on_closing(self) -> None: + self.parent.destroy() + get_event_loop().stop() + + async def get_transcribe(self) -> None: + if not self.preference.check_if_ar_key_exists(): + self.on_error_occurs(self.render_text(constants.ERROR_API_KEY)) + + self.disable_entries() + self.output_area.insert(tk.INSERT, "Please wait....\n") + file_path = Path(self.input_path.get()) + output_path = Path(self.output_path.get() + f"/{file_path.stem}.txt") + config_path = Path(self.preference.get_config_file()) + try: + api_client = WitAiAPI( + "ar", 5, config_path, bool(self.verbose_checkbox_var.get()) + ) + await api_client.transcribe(file_path) + Path(output_path).write_text(api_client.text, encoding="utf-8") + except: + self.output_area.insert(tk.INSERT, "Error occurs! Please try again!") + self.enable_entries() + self.enable_entries() + + def disable_entries(self) -> None: + self.input_entry.config(state="disabled") + self.output_entry.config(state="disabled") + self.startTranscribe["state"] = tk.DISABLED + + def enable_entries(self) -> None: + self.input_entry.config(state="normal") + self.output_entry.config(state="normal") + self.startTranscribe["state"] = tk.NORMAL + + async def exec(self) -> None: + await self.show() + + def render_text(self, text: str) -> str: + return _text(self._platform, text) diff --git a/wit_transcriber/gui/preferences.py b/wit_transcriber/gui/preferences.py new file mode 100644 index 0000000..2e815bc --- /dev/null +++ b/wit_transcriber/gui/preferences.py @@ -0,0 +1,42 @@ +import json +from pathlib import Path +from typing import Dict + + +class PreferencesManager: + def __init__(self, path: Path) -> None: + self.filename: Path = path / "config.json" + self.settings_object: Dict[str, str] = {} + if not self.filename.exists(): + self.create_preferences_file() + else: + self.load_preferences_file() + + def load_preferences_file(self) -> None: + self.settings_object = json.loads(self.filename.read_text()) + + def create_preferences_file(self) -> None: + self.settings_object = { + "ar": "", + } + self.update_preferences_file() + + def update_preferences_file(self) -> None: + self.filename.write_text(json.dumps(self.settings_object, indent=4)) + + def put(self, key: str, value: str) -> None: + self.settings_object[key] = value + self.update_preferences_file() + + def get(self, key: str) -> str: + self.load_preferences_file() + return self.settings_object[key] + + def get_json(self) -> Dict[str, str]: + return self.settings_object + + def check_if_ar_key_exists(self) -> str: + return self.get("ar") + + def get_config_file(self) -> Path: + return Path(self.filename) diff --git a/wit_transcriber/gui/settings.py b/wit_transcriber/gui/settings.py new file mode 100644 index 0000000..5d7b840 --- /dev/null +++ b/wit_transcriber/gui/settings.py @@ -0,0 +1,102 @@ +import tkinter as tk +import tkinter.font as tkFont +from tkinter import messagebox +from typing import Callable + +from wit_transcriber.gui.preferences import PreferencesManager + + +class SettingWindow: + """ + Window is designed by using https://visualtk.com/ + """ + + def __init__( + self, parent: tk.Tk, preferences: PreferencesManager, render_text: Callable + ) -> None: + self.parent: tk.Tk = parent + self.preferences: PreferencesManager = preferences + self.render_text = render_text + self.window = tk.Toplevel(self.parent) + # window.geometry("400x250") + # setting window size + width = 400 + height = 300 + screenwidth = self.window.winfo_screenwidth() + screenheight = self.window.winfo_screenheight() + align_str = f"{width:.0f}x{height:.0f}+{(screenwidth - width) / 2:.0f}+{(screenheight - height) / 2:.0f}" + self.window.geometry(align_str) + self.window.resizable(width=False, height=False) + self.window.title("الإعدادات") + ft = tkFont.Font(family="Tajawal", size=10) + + setting_main_title = tk.Label( + self.window, + font=ft, + fg="#333333", + justify="center", + text=self.render_text("إعدادات البرنامج"), + ) + setting_main_title.place(x=140, y=20, width=200, height=25) + + self.ar_lang_entry_str_var = tk.StringVar() + self.ar_lang_entry_str_var.set("ar") + ar_lang_entry = tk.Entry( + self.window, + textvariable=self.ar_lang_entry_str_var, + borderwidth="1px", + font=ft, + justify="left", + state="disabled", + ) + ar_lang_entry.place(x=30, y=80, width=109, height=32) + + self.ar_api_key_entry_str_var = tk.StringVar() + self.ar_api_key_entry_str_var.set(self.preferences.get("ar")) + ar_api_key_entry = tk.Entry( + self.window, + textvariable=self.ar_api_key_entry_str_var, + borderwidth="1px", + font=ft, + justify="left", + ) + ar_api_key_entry.place(x=170, y=80, width=213, height=30) + + ar_lang_label = tk.Label( + self.window, + font=ft, + fg="#333333", + justify="left", + text=self.render_text("اللغة العربية"), + ) + ar_lang_label.place(x=30, y=50, width=70, height=25) + + ar_api_key_label = tk.Label( + self.window, + font=ft, + fg="#333333", + justify="center", + text=self.render_text("مفتاح التفعيل"), + ) + ar_api_key_label.place(x=170, y=50, width=100, height=25) + + save_btn = tk.Button( + self.window, + bg="#f0f0f0", + fg="#000000", + font=ft, + justify="center", + text=self.render_text("حفظ"), + command=self.save_settings, + ) + save_btn.place(x=160, y=250, width=70, height=25) + + def save_settings(self) -> None: + self.preferences.put("ar", self.ar_api_key_entry_str_var.get()) + self.show_info(self.render_text("تم حفظ الإعدادات بنجاح!")) + + def show_info(self, msg: str) -> None: + messagebox.showinfo(self.render_text("إعدادات"), msg) + + def load_preference_settings(self) -> None: + self.ar_api_key_entry_str_var.set(self.preferences.get("ar")) diff --git a/wit_transcriber/gui/utils.py b/wit_transcriber/gui/utils.py new file mode 100644 index 0000000..1149f94 --- /dev/null +++ b/wit_transcriber/gui/utils.py @@ -0,0 +1,6 @@ +from awesometkinter.bidirender import render_text + + +def _text(platform: str, text: str) -> str: + """A helper function to get text in correct direction based on OS.""" + return render_text(text) if platform != "Windows" else text diff --git a/wit_transcriber_gui.spec b/wit_transcriber_gui.spec new file mode 100644 index 0000000..d51f3f1 --- /dev/null +++ b/wit_transcriber_gui.spec @@ -0,0 +1,44 @@ +# -*- mode: python ; coding: utf-8 -*- + + +block_cipher = None + + +a = Analysis( + ['wit_transcriber/gui/app.py'], + pathex=[], + binaries=[], + datas=[('pyproject.toml', '.')], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False, +) +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.zipfiles, + a.datas, + [], + name='wit_transcriber_gui', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +)