textflowkit 0.1.9__tar.gz → 0.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.github/workflows/ci.yml +1 -1
- {textflowkit-0.1.9 → textflowkit-0.1.11}/CHANGELOG.md +92 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/CONTRIBUTING.md +7 -1
- {textflowkit-0.1.9 → textflowkit-0.1.11}/PKG-INFO +138 -24
- {textflowkit-0.1.9 → textflowkit-0.1.11}/README.md +131 -23
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/adapters.md +118 -4
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/architecture.md +73 -4
- textflowkit-0.1.11/docs/assets/architecture-overview.svg +213 -0
- textflowkit-0.1.11/docs/assets/live-streaming-flow.svg +50 -0
- textflowkit-0.1.11/docs/assets/local-ui-flow.svg +155 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/index.html +46 -9
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/install.md +53 -1
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/release-checklist.md +48 -1
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/roadmap.md +39 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/site-deployment.md +10 -2
- textflowkit-0.1.11/docs/streaming.md +514 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/user-manual.md +144 -17
- {textflowkit-0.1.9 → textflowkit-0.1.11}/pyproject.toml +17 -2
- textflowkit-0.1.11/scripts/smoke_installed_wheel.py +436 -0
- textflowkit-0.1.11/src/textflowkit/__init__.py +41 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/adapters/http_server.py +258 -2
- textflowkit-0.1.11/src/textflowkit/adapters/streaming_ws.py +1276 -0
- textflowkit-0.1.11/src/textflowkit/core/stream_worker.py +227 -0
- textflowkit-0.1.11/src/textflowkit/core/streaming.py +1198 -0
- textflowkit-0.1.11/src/textflowkit/core/streaming_assets.py +542 -0
- textflowkit-0.1.11/src/textflowkit/core/streaming_events.py +330 -0
- textflowkit-0.1.11/src/textflowkit/core/streaming_process.py +520 -0
- textflowkit-0.1.11/src/textflowkit/ui/__init__.py +13 -0
- textflowkit-0.1.11/src/textflowkit/ui/app.py +711 -0
- textflowkit-0.1.11/src/textflowkit/ui/capabilities.py +195 -0
- textflowkit-0.1.11/src/textflowkit/ui/launcher.py +711 -0
- textflowkit-0.1.11/src/textflowkit/ui/ownership.py +602 -0
- textflowkit-0.1.11/src/textflowkit/ui/paths.py +179 -0
- textflowkit-0.1.11/src/textflowkit/ui/security.py +200 -0
- textflowkit-0.1.11/src/textflowkit/ui/static/app.css +285 -0
- textflowkit-0.1.11/src/textflowkit/ui/static/app.js +756 -0
- textflowkit-0.1.11/src/textflowkit/ui/static/index.html +226 -0
- textflowkit-0.1.11/src/textflowkit/ui/static/streaming-capture-worklet.js +156 -0
- textflowkit-0.1.11/src/textflowkit/ui/static/streaming-example.html +699 -0
- textflowkit-0.1.11/src/textflowkit/ui/uploads.py +247 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_landing_commands.py +28 -11
- textflowkit-0.1.11/tests/test_streaming_assets.py +320 -0
- textflowkit-0.1.11/tests/test_streaming_browser_lifecycle.py +1347 -0
- textflowkit-0.1.11/tests/test_streaming_core.py +654 -0
- textflowkit-0.1.11/tests/test_streaming_example.py +371 -0
- textflowkit-0.1.11/tests/test_streaming_repairs.py +950 -0
- textflowkit-0.1.11/tests/test_streaming_transport.py +837 -0
- textflowkit-0.1.11/tests/test_streaming_u5_repairs.py +917 -0
- textflowkit-0.1.11/tests/test_streaming_ui_integration.py +190 -0
- textflowkit-0.1.11/tests/test_ui_assets_and_capabilities.py +294 -0
- textflowkit-0.1.11/tests/test_ui_consoleless_logging.py +88 -0
- textflowkit-0.1.11/tests/test_ui_existing_routes_unchanged.py +86 -0
- textflowkit-0.1.11/tests/test_ui_launcher.py +224 -0
- textflowkit-0.1.11/tests/test_ui_ownership_and_shutdown.py +477 -0
- textflowkit-0.1.11/tests/test_ui_packaging.py +164 -0
- textflowkit-0.1.11/tests/test_ui_real_serve.py +88 -0
- textflowkit-0.1.11/tests/test_ui_security.py +168 -0
- textflowkit-0.1.11/tests/test_ui_submission_and_download.py +260 -0
- textflowkit-0.1.11/tests/test_ui_uploads.py +201 -0
- textflowkit-0.1.9/docs/assets/architecture-overview.svg +0 -189
- textflowkit-0.1.9/scripts/smoke_installed_wheel.py +0 -219
- textflowkit-0.1.9/src/textflowkit/__init__.py +0 -8
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.dockerignore +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.env.example +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.gitattributes +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.github/dependabot.yml +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.github/workflows/publish-pypi.yml +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.gitignore +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/.pre-commit-config.yaml +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/Dockerfile +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/LEGAL.md +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/LICENSE +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/SECURITY.md +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/compose.yaml +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/.nojekyll +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/404.html +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/assets/whistle-resume.svg +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/docs/sources.md +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/scripts/fetch_published_fonts.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/scripts/smoke_live_youtube.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/scripts/verify_readme_release.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/scripts/verify_release_ci.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/scripts/verify_release_versions.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/scripts/write_release_manifest.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/adapters/__init__.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/adapters/mcp_server.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/assets/README.md +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/assets/selftest-speech.wav +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/cli.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/__init__.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/batch.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/bind.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/cancel.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/checkpoint.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/diarize.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/engine.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/executor.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/jobs.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/model.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/paths.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/pipeline.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/retrieval.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/runner.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/service.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/sqlite_store.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/startup.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/submission.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/timeutil.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/translate.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/whistle.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/core/whistle_assets.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/__init__.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/_cue_layout.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/_cue_text.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/_rename_excl.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/_rename_noreplace.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/docx.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/markdown.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/pdf.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/srt.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/txt.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/render/vtt.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/sources/__init__.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/sources/acquire.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/sources/detect.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/src/textflowkit/sources/scratch.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/__init__.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/ollama_stub.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_acquire.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_adapters.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_admission_ownership.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_atomic_resume.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_atomic_resume_aba.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_batch.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_batch_item_boundary.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_batch_resume_shared.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_bind.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cancellation_finalization.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_checkpoint.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_checkpoint_single_copy.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cli.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cli_batch_feedback.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cli_owning_recovery.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cli_resume_batch.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cli_stage_feedback.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cli_stdout_format.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_confined_decoder_boundary.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_confined_indirect_media.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_confined_resume_boundary.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_container_example.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_cue_layout.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_diarize.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_diarize_example_flags.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_diarize_token_docs.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_docx_publication_identity.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_done_output_integrity.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_empty_formats_resume.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_engine_adapters.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_engine_cache.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_engine_faster.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_engine_quiet.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_executor.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_executor_store_failure.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_export.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_export_file_mode.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_export_preflight.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_faster_whisper_docs.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_fetch_published_fonts.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_font_notices.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_http_host_boundary.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_http_trusted_proxy.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_job_progress.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_jobs.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_landing_page.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_legal_summary.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_linux_no_hardlink.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_live_smoke_script.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_macos_no_hardlink.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_mcp_batch_cookie_docs.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_mcp_http_boundary.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_mcp_protocol_cleanliness.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_mcp_terminal_guidance.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_mcp_tool_descriptions.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_mcp_work_root.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_model.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_partial_output_resume.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_partial_pdf_resume.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_paths.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_pipeline_integrity.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_pipeline_resume_setup.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_production_browser_cookies.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_publish_ci_gate.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_publish_fonts_wiring.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_publish_manifest_wiring.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_publish_workflow_gate.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_readme_layout.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_readme_release_guard.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_release_boundaries.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_release_manifest.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_release_surfaces.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_render.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_retrieval.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_sdist_allowlist.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_service_profile.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_site_not_found.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_sources.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_stage_reuse_resume.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_startup_recovery.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_stdio_protocol.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_submission.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_submission_validation.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_translate.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_translate_completeness.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_verify_release_versions.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_whistle_assets.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_whistle_defaults.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_whistle_engine.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_whistle_job_resume.py +0 -0
- {textflowkit-0.1.9 → textflowkit-0.1.11}/tests/test_windows_no_hardlink.py +0 -0
|
@@ -90,6 +90,6 @@ jobs:
|
|
|
90
90
|
python -m pip install "setuptools>=83" "build>=1.2"
|
|
91
91
|
python -m build --wheel
|
|
92
92
|
python -m build --wheel --outdir dist packages/textflowkit-fonts
|
|
93
|
-
- name: Smoke all
|
|
93
|
+
- name: Smoke all four installed entry points (CLI, MCP, HTTP, served UI)
|
|
94
94
|
shell: bash
|
|
95
95
|
run: python scripts/smoke_installed_wheel.py dist/textflowkit-*.whl dist/textflowkit_fonts-*.whl
|
|
@@ -1,5 +1,97 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.1.11 — 2026-10-06
|
|
4
|
+
|
|
5
|
+
Optional native live streaming supports **Windows x86_64 only**. Core version:
|
|
6
|
+
0.1.11; unchanged optional fonts: 0.1.6. Existing standalone Whistle defaults,
|
|
7
|
+
file/URL jobs, CLI, and MCP behavior are unchanged. The public site remains static
|
|
8
|
+
documentation and serves no streams. Local source validation does not establish
|
|
9
|
+
published-package verification or cross-platform live support.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Public `StreamingSession` API.** Bounded PCM feed, typed incremental events,
|
|
15
|
+
flush/finish, cancellation, canonical final `Transcript`, and context-manager
|
|
16
|
+
cleanup. One owned native child per session binds directly to the separately
|
|
17
|
+
pinned `libneedle3.dll`; no upstream Python SDK or telemetry module is loaded.
|
|
18
|
+
Live sessions are ephemeral, with no replay or durable resume.
|
|
19
|
+
- **Live microphone streaming (opt-in, loopback-only).** When
|
|
20
|
+
`TEXTFLOWKIT_STREAMING=1` is set, the developer HTTP app serves a `/stream`
|
|
21
|
+
WebSocket and the local UI serves `/api/stream`, both transcribing audio as it
|
|
22
|
+
arrives. A runnable, self-hosted browser example is at `/streaming-example`
|
|
23
|
+
(and `/api/streaming-example` under the UI); its `AudioWorklet` resamples any
|
|
24
|
+
device rate to 16 kHz mono with continuous phase. Off by default: with the
|
|
25
|
+
switch unset the endpoint does not exist. The standalone `textflowkit` CLI is
|
|
26
|
+
unaffected — it does not open a microphone or a streaming socket. Requires the
|
|
27
|
+
new `streaming` extra (`pip install "textflowkit[streaming]"`), which adds the
|
|
28
|
+
`websockets` dependency. Auth is fail-closed: the UI accepts only its own origin
|
|
29
|
+
and capability, the standalone API requires the API token (even in developer
|
|
30
|
+
mode), and a separate origin may stream only if the operator lists it in
|
|
31
|
+
`TEXTFLOWKIT_STREAMING_ORIGINS` (a browser needs its own origin listed, including
|
|
32
|
+
the standalone example's). See [docs/streaming.md](docs/streaming.md).
|
|
33
|
+
**Bounded live runs verified on this machine's native engine** — 65 s and 300 s
|
|
34
|
+
through the product core on Windows x86_64. A separate assembled UI WebSocket
|
|
35
|
+
run fed prerecorded PCM at real time for 12 s. Browser lifecycle and resampling
|
|
36
|
+
checks used fake audio; **physical microphone capture was not verified**. Only
|
|
37
|
+
English was measured natively; the other six accepted languages and live
|
|
38
|
+
Linux/macOS were not exercised. No public remote streaming is provided.
|
|
39
|
+
|
|
40
|
+
## v0.1.10 — 2026-10-06
|
|
41
|
+
|
|
42
|
+
**The local browser interface ships.** The loopback-only browser workspace
|
|
43
|
+
(`textflowkit-ui`) is now part of the core package rather than source-only, so a
|
|
44
|
+
regular install of this release carries the command. Core version: 0.1.10;
|
|
45
|
+
unchanged optional fonts: 0.1.6.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- **Local browser interface in the core package.** `textflowkit-ui` serves a
|
|
50
|
+
point-and-click workspace on **this machine only**: it binds `127.0.0.1` (never
|
|
51
|
+
off the machine, whatever `TEXTFLOWKIT_ALLOW_REMOTE` is set to) and opens a
|
|
52
|
+
browser once serving. It mounts the existing developer HTTP app under `/api`
|
|
53
|
+
**unchanged** — the same routes, submission contract, and job store — and adds
|
|
54
|
+
only transport: a loopback session layer, a streamed upload, a fixed-format
|
|
55
|
+
download, in-workspace playback, and a capability endpoint. It adds **no new
|
|
56
|
+
dependency** beyond the existing `http` extra (FastAPI + uvicorn).
|
|
57
|
+
- **Durable jobs, cancel and resume in the workspace.** Jobs and checkpoints are
|
|
58
|
+
stored durably under the per-user data directory unless
|
|
59
|
+
`TEXTFLOWKIT_DB` / `TEXTFLOWKIT_WORK_ROOT` / `TEXTFLOWKIT_OUTPUT_ROOT` is set.
|
|
60
|
+
A dropped file is streamed and capped at **2 GiB** by default
|
|
61
|
+
(`TEXTFLOWKIT_UI_MAX_UPLOAD_BYTES` overrides it). A running job can be
|
|
62
|
+
cancelled, and a durable job resumed.
|
|
63
|
+
- **Windows desktop shortcut.** `textflowkit-ui --create-shortcut` creates a Start
|
|
64
|
+
Menu entry that launches with `pythonw` (no console) and needs no `pywin32`.
|
|
65
|
+
Under `pythonw` a startup failure is logged under the per-user data directory
|
|
66
|
+
and shown in a message box rather than failing silently.
|
|
67
|
+
- **Controlled shutdown that drains.** **Stop server** asks this process's own
|
|
68
|
+
uvicorn server to exit through its supported `should_exit` flag; the normal
|
|
69
|
+
lifespan teardown **waits for current jobs to finish** before draining the
|
|
70
|
+
worker pool rather than interrupting them, so a running job's saved progress
|
|
71
|
+
survives and is resumable. It never sends a signal to a pid.
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- **Documentation surfaces.** README, user manual, install notes, developer
|
|
76
|
+
manual, architecture guide, roadmap, release checklist, site deployment, the
|
|
77
|
+
landing page, and the checked-in SVG diagrams now describe the local browser
|
|
78
|
+
interface as a shipped feature and a fifth door, and remove the earlier
|
|
79
|
+
"unreleased candidate / install from source only" wording.
|
|
80
|
+
- **No endpoint-breaking change.** The CLI, Python API, MCP server, and JSON HTTP
|
|
81
|
+
adapter are unchanged in this release; the optional engines, diarization, and
|
|
82
|
+
translation keep their documented dependency requirements.
|
|
83
|
+
|
|
84
|
+
### Verification boundary
|
|
85
|
+
|
|
86
|
+
Automated coverage runs the UI's routes, packaging, ownership/shutdown, and
|
|
87
|
+
security boundaries. A **native Windows** machine, in a real browser, proved the
|
|
88
|
+
workspace end to end (drop a file, submit, download, stop). That is one platform's
|
|
89
|
+
browser proof, **not** a live Linux or macOS UI run — those platforms are covered
|
|
90
|
+
by automated tests only, and cross-platform CI (Windows/Linux/macOS) is a separate
|
|
91
|
+
release gate. **No live optional-backend (translation or
|
|
92
|
+
diarization) run through the UI is claimed.** The engine and packaging changes of
|
|
93
|
+
v0.1.9 are unchanged by this release.
|
|
94
|
+
|
|
3
95
|
## v0.1.9 — 2026-10-05
|
|
4
96
|
|
|
5
97
|
**Whistle is now the default engine.** This release ships the Whistle integration
|
|
@@ -14,9 +14,15 @@ python -m venv .venv
|
|
|
14
14
|
# Windows: .venv\Scripts\activate
|
|
15
15
|
# POSIX: source .venv/bin/activate
|
|
16
16
|
pip install ./packages/textflowkit-fonts # local optional PDF font companion
|
|
17
|
-
pip install -e ".[dev,mcp,http,export]"
|
|
17
|
+
pip install -e ".[dev,mcp,http,streaming,export,whisper]"
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
The full suite needs both `streaming` (WebSocket transport) and `whisper`
|
|
21
|
+
(optional standalone engine) dependencies. Use a development environment; for
|
|
22
|
+
an existing AMD ROCm torch stack, follow [the install guide](docs/install.md)
|
|
23
|
+
to preserve that stack. Native live streaming supports Windows x86_64 only;
|
|
24
|
+
ordinary standalone platform support and defaults remain unchanged.
|
|
25
|
+
|
|
20
26
|
## Test and lint — the commands CI runs
|
|
21
27
|
|
|
22
28
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: textflowkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: Cross-platform media transcription toolkit: URL or file in, timestamped transcripts and subtitle files out.
|
|
5
5
|
Project-URL: Homepage, https://www.textflowkit.org/
|
|
6
6
|
Project-URL: Issues, https://github.com/scottconverse/textflowkit/issues
|
|
@@ -32,6 +32,7 @@ Requires-Dist: python-docx>=1.1; extra == 'all'
|
|
|
32
32
|
Requires-Dist: reportlab>=4.0; extra == 'all'
|
|
33
33
|
Requires-Dist: textflowkit-fonts<0.2,>=0.1.5; extra == 'all'
|
|
34
34
|
Requires-Dist: uvicorn>=0.30; extra == 'all'
|
|
35
|
+
Requires-Dist: websockets<16,>=15; extra == 'all'
|
|
35
36
|
Provides-Extra: dev
|
|
36
37
|
Requires-Dist: build>=1.2; extra == 'dev'
|
|
37
38
|
Requires-Dist: hatchling>=1.25; extra == 'dev'
|
|
@@ -53,6 +54,11 @@ Requires-Dist: pydantic>=2.7; extra == 'http'
|
|
|
53
54
|
Requires-Dist: uvicorn>=0.30; extra == 'http'
|
|
54
55
|
Provides-Extra: mcp
|
|
55
56
|
Requires-Dist: mcp>=2.0; extra == 'mcp'
|
|
57
|
+
Provides-Extra: streaming
|
|
58
|
+
Requires-Dist: fastapi>=0.115; extra == 'streaming'
|
|
59
|
+
Requires-Dist: pydantic>=2.7; extra == 'streaming'
|
|
60
|
+
Requires-Dist: uvicorn>=0.30; extra == 'streaming'
|
|
61
|
+
Requires-Dist: websockets<16,>=15; extra == 'streaming'
|
|
56
62
|
Provides-Extra: whisper
|
|
57
63
|
Requires-Dist: openai-whisper>=20240930; extra == 'whisper'
|
|
58
64
|
Description-Content-Type: text/markdown
|
|
@@ -67,7 +73,7 @@ Cross-platform media transcription toolkit. **One core, one CLI, thin adapters.*
|
|
|
67
73
|
[User manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md) ·
|
|
68
74
|
[Developer and integration manual](https://github.com/scottconverse/textflowkit/blob/main/docs/adapters.md)
|
|
69
75
|
|
|
70
|
-
**Current release: [v0.1.
|
|
76
|
+
**Current release: [v0.1.11](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.11).**
|
|
71
77
|
|
|
72
78
|
The [static site deployment](https://github.com/scottconverse/textflowkit/blob/main/docs/site-deployment.md) is hosted on Cloudflare
|
|
73
79
|
Pages. GitHub remains the source and CI host; the website does not run the
|
|
@@ -128,10 +134,11 @@ DOCX and PDF are available through the optional `export` extra.
|
|
|
128
134
|
|
|
129
135
|
## Architecture
|
|
130
136
|
|
|
131
|
-

|
|
132
138
|
|
|
133
|
-
The design principle is **one
|
|
134
|
-
the core; the interfaces are thin
|
|
139
|
+
The design principle is **one shared core, thin doors**. Everything of substance
|
|
140
|
+
lives in the core; the interfaces are thin — the local browser UI is a fifth door
|
|
141
|
+
that adds only transport over the existing HTTP app and shared job store.
|
|
135
142
|
|
|
136
143
|
| Layer | Path | Responsibility |
|
|
137
144
|
|---|---|---|
|
|
@@ -141,6 +148,7 @@ the core; the interfaces are thin.
|
|
|
141
148
|
| **CLI** | `src/textflowkit/cli.py` | Reference interface (subprocess-friendly) |
|
|
142
149
|
| **MCP** | `src/textflowkit/adapters/mcp_server.py` | stdio + Streamable HTTP, for AI harnesses |
|
|
143
150
|
| **HTTP** | `src/textflowkit/adapters/http_server.py` | JSON API, for software products and web frontends |
|
|
151
|
+
| **Local UI** | `src/textflowkit/ui` | Loopback-only browser workspace over the same HTTP app and job store |
|
|
144
152
|
|
|
145
153
|
Because the core owns the pipeline, adding a door is cheap — and adding a platform
|
|
146
154
|
means writing one source adapter, not another tool.
|
|
@@ -148,6 +156,32 @@ means writing one source adapter, not another tool.
|
|
|
148
156
|
For the job lifecycle, process ownership, checkpoints, and output publication,
|
|
149
157
|
see [docs/architecture.md](https://github.com/scottconverse/textflowkit/blob/main/docs/architecture.md).
|
|
150
158
|
|
|
159
|
+
## Live microphone streaming (opt-in)
|
|
160
|
+
|
|
161
|
+
In v0.1.11, live streaming supports **Windows x86_64 only**. When
|
|
162
|
+
`TEXTFLOWKIT_STREAMING=1` is set, the developer HTTP app serves a `/stream`
|
|
163
|
+
WebSocket and the local UI serves `/api/stream`, both transcribing a live microphone
|
|
164
|
+
as you speak. A **runnable, self-hosted browser example** ships at
|
|
165
|
+
`/streaming-example` (and `/api/streaming-example` under the UI): it captures with an
|
|
166
|
+
`AudioWorklet`, resamples any device rate to 16 kHz mono, and shows the transcript.
|
|
167
|
+
No CDN, no analytics, no external fetch. Requires the `streaming` extra:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
python -m pip install "textflowkit[streaming]==0.1.11"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
It is **off by default** — with the switch unset the endpoint does not exist — and
|
|
174
|
+
**loopback-only**: auth is fail-closed, so the UI accepts only its own origin and
|
|
175
|
+
capability, the standalone API requires `TEXTFLOWKIT_API_TOKEN` (even in developer
|
|
176
|
+
mode), and a separate origin — including the standalone browser example's own origin —
|
|
177
|
+
may stream only if listed in `TEXTFLOWKIT_STREAMING_ORIGINS`. The standalone
|
|
178
|
+
`textflowkit` CLI is unaffected: it does not open a microphone or a streaming socket.
|
|
179
|
+
**Bounded live runs are verified on the native engine here** — 65 s and 300 s
|
|
180
|
+
end-to-end on Windows x86_64; the transport and the browser resampler are covered by
|
|
181
|
+
tests, and a physical browser microphone has not yet been captured (the browser proof
|
|
182
|
+
drives the page against a fake audio device). See
|
|
183
|
+
[docs/streaming.md](https://github.com/scottconverse/textflowkit/blob/main/docs/streaming.md).
|
|
184
|
+
|
|
151
185
|
## Recognized sources
|
|
152
186
|
|
|
153
187
|
YouTube · TikTok · Facebook · Instagram · Vimeo · Twitch · Bilibili · Rumble ·
|
|
@@ -294,7 +328,7 @@ textflowkit export ./transcript.json --format vtt
|
|
|
294
328
|
needs no PyTorch, so a fresh `pip install textflowkit` stays small and pulls no
|
|
295
329
|
torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
296
330
|
|
|
297
|
-
, each core runs as one owned child with forced telemetry-off flags, a partial checkpoint is written after each core, and a resume validates the source and decoded-WAV hashes then re-runs only the unfinished cores.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.11/docs/assets/whistle-resume.svg)
|
|
298
332
|
|
|
299
333
|
- **CPU only, no torch.** It runs a pinned native binary and downloads one pinned
|
|
300
334
|
model on first use. Naming a GPU device is refused rather than silently
|
|
@@ -311,7 +345,7 @@ torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
|
311
345
|
of context on each side, so every standalone clip is ≤ 30 seconds (the native
|
|
312
346
|
CLI's limit). Overlap words are selected by core midpoint rather than text
|
|
313
347
|
deduplication, so repeated spoken phrases are preserved.
|
|
314
|
-
- **
|
|
348
|
+
- **Standalone streaming is not used.** The native `--audio-stream` mode failed its
|
|
315
349
|
coverage and is never passed; only the committed standalone output is parsed.
|
|
316
350
|
- **Durable block resume.** With `TEXTFLOWKIT_DB` set, a long run writes partial
|
|
317
351
|
per-block checkpoints; a resume checks the source and decoded-WAV hashes and the
|
|
@@ -397,6 +431,66 @@ contract checks cover it, and running an actual build is deliberately out of
|
|
|
397
431
|
scope here, so no image is claimed to build or start. See
|
|
398
432
|
[the container example](https://github.com/scottconverse/textflowkit/blob/main/docs/adapters.md#container-example-dockerfile-and-compose).
|
|
399
433
|
|
|
434
|
+
## Local browser interface
|
|
435
|
+
|
|
436
|
+
For point-and-click use there is a local browser workspace that runs on **this
|
|
437
|
+
machine only**, reuses the same pipeline and job store, and adds no dependency of
|
|
438
|
+
its own beyond the `http` extra. It ships with the core package as of v0.1.10:
|
|
439
|
+
a regular install of the current release carries it.
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
python -m pip install 'textflowkit[http,export]==0.1.11'
|
|
443
|
+
textflowkit-ui
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
On Windows you can create a desktop shortcut when you want one:
|
|
447
|
+
|
|
448
|
+
```powershell
|
|
449
|
+
textflowkit-ui --create-shortcut # Start Menu entry (pythonw, no console)
|
|
450
|
+
textflowkit-ui --create-shortcut --shortcut-dir 'C:\path\to\folder'
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
The shortcut is created only on request and needs no `pywin32`. Under `pythonw`
|
|
454
|
+
there is no console, so a startup failure is written to a log file under the
|
|
455
|
+
per-user data directory and shown in a message box rather than failing silently.
|
|
456
|
+
The normal operator path is to launch from that shortcut; the console command
|
|
457
|
+
above is equivalent.
|
|
458
|
+
|
|
459
|
+
**This is a local app, not a public website.** The [landing page](https://www.textflowkit.org/)
|
|
460
|
+
is static documentation served by Cloudflare Pages; it does **not** run the
|
|
461
|
+
transcription engine and offers no upload form. The browser workspace exists only
|
|
462
|
+
on the machine that installed it.
|
|
463
|
+
|
|
464
|
+
- **Loopback only.** It binds `127.0.0.1` (never off the machine, whatever
|
|
465
|
+
`TEXTFLOWKIT_ALLOW_REMOTE` is set to) and opens a browser once it is serving.
|
|
466
|
+
- **One owner per database.** A second launch against the same database opens the
|
|
467
|
+
UI already running rather than starting a competing server. **Stop server** in
|
|
468
|
+
the workspace shuts the local server down without a terminal, waiting for the
|
|
469
|
+
current jobs to finish rather than interrupting them. Shutdown **drains** — it
|
|
470
|
+
lets in-flight jobs complete; it does **not** auto-cancel them. Cancel a job
|
|
471
|
+
first to stop it early.
|
|
472
|
+
- **Durable jobs with cancel and resume.** Jobs and checkpoints are stored
|
|
473
|
+
durably under the per-user data directory unless you set `TEXTFLOWKIT_DB` /
|
|
474
|
+
`TEXTFLOWKIT_WORK_ROOT` / `TEXTFLOWKIT_OUTPUT_ROOT`. A dropped file is capped
|
|
475
|
+
at **2 GiB** by default (`TEXTFLOWKIT_UI_MAX_UPLOAD_BYTES` overrides it).
|
|
476
|
+
In-workspace playback uses the browser's native player on the **currently
|
|
477
|
+
selected** media, so it depends on what that browser can decode; it is a
|
|
478
|
+
convenience preview, not a format guarantee.
|
|
479
|
+
- **No UI analytics.** The page loads no CDN asset and no analytics, and the
|
|
480
|
+
session token lives only in the page — never in a URL, cookie, or log line.
|
|
481
|
+
- **What uses the network.** The page itself loads nothing remote. A **URL
|
|
482
|
+
source** is downloaded from the internet; an engine's **model** may be
|
|
483
|
+
downloaded on first use; and **remote or cloud translation** (an advanced
|
|
484
|
+
option) sends transcript text to that backend. With local media and a local
|
|
485
|
+
translation model, no transcript leaves the machine.
|
|
486
|
+
- `--port`, `--no-browser`, and `--version` are available.
|
|
487
|
+
|
|
488
|
+
The other doors are unchanged: the CLI, Python API, MCP, and HTTP adapters keep
|
|
489
|
+
their existing behavior, and the optional engines, diarization, and translation
|
|
490
|
+
retain their documented dependency requirements. See the
|
|
491
|
+
[user manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md#7-local-browser-interface)
|
|
492
|
+
and [architecture guide](https://github.com/scottconverse/textflowkit/blob/main/docs/architecture.md#one-owner-per-database).
|
|
493
|
+
|
|
400
494
|
## Durable, bounded, cancellable
|
|
401
495
|
|
|
402
496
|
```bash
|
|
@@ -411,23 +505,43 @@ boundary. See [docs/adapters.md](https://github.com/scottconverse/textflowkit/bl
|
|
|
411
505
|
|
|
412
506
|
The MCP and HTTP adapters are **job-based**: submission returns a job id
|
|
413
507
|
immediately and clients poll for completion. The CLI uses the same core but
|
|
414
|
-
waits for the result. This lets AI harnesses, software products, and
|
|
415
|
-
|
|
508
|
+
waits for the result. This lets AI harnesses, software products, and the local
|
|
509
|
+
browser interface share the job contract without blocking a request.
|
|
416
510
|
|
|
417
511
|
## Status
|
|
418
512
|
|
|
419
|
-
**v0.1.
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
`
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
513
|
+
**v0.1.11 release.** Optional live streaming adds a transport-neutral
|
|
514
|
+
`StreamingSession` Python API, incremental transcript events, and authenticated
|
|
515
|
+
loopback WebSockets (`/stream` on the developer HTTP API and `/api/stream` on the
|
|
516
|
+
local UI), with a packaged browser microphone example. The native live capability
|
|
517
|
+
supports **Windows x86_64 only** and uses one owned child with a separately pinned
|
|
518
|
+
`libneedle3.dll`. The `streaming` extra supplies the WebSocket dependency;
|
|
519
|
+
`TEXTFLOWKIT_STREAMING=1` enables the server routes. Streaming is off by default.
|
|
520
|
+
|
|
521
|
+
Existing file and URL transcription, CLI, MCP, durable jobs, and local browser
|
|
522
|
+
workspace defaults remain unchanged. Whistle stays the CPU-only standalone default;
|
|
523
|
+
`openai-whisper` remains an explicit opt-in engine. The local browser workspace
|
|
524
|
+
introduced in v0.1.10 still needs only the `http` extra for its ordinary job flow.
|
|
525
|
+
Fonts remain 0.1.6. Live sessions are ephemeral and have no durable resume.
|
|
526
|
+
|
|
527
|
+
**Streaming evidence.** Local English PCM runs exercised the native core for 65 s
|
|
528
|
+
and 300 s; a separate assembled UI WebSocket run fed prerecorded PCM at real time
|
|
529
|
+
for 12 s and returned incremental events and a final transcript. Browser lifecycle
|
|
530
|
+
and resampling checks used fake audio. Physical browser microphone capture, live
|
|
531
|
+
Linux/macOS, and the six other accepted languages were not verified. The public
|
|
532
|
+
website remains static documentation and serves no streaming endpoint. Local source
|
|
533
|
+
validation does not establish published-package or exact-commit CI results.
|
|
534
|
+
|
|
535
|
+
**Verification limit.** The local browser interface is covered by an automated
|
|
536
|
+
suite, and the UI's behavior was proved on a **native Windows** machine in a real
|
|
537
|
+
browser. No live optional-backend (translation/diarization) run through the UI is
|
|
538
|
+
claimed, and **no live Linux or macOS UI run was performed here** — those
|
|
539
|
+
platforms are covered by automated tests only, and CI across Windows, Linux, and
|
|
540
|
+
macOS is a separate release gate. Release publication uses the tag
|
|
541
|
+
workflow, which requires successful exact-commit main CI before PyPI uploads and
|
|
542
|
+
creates the public GitHub release only afterward. Check the linked release for
|
|
543
|
+
artifacts and workflow status; local source verification is not a fresh
|
|
544
|
+
PyPI-install or individual-harness receipt.
|
|
431
545
|
|
|
432
546
|
The v0.1.8 release carried four fixes for the 2026-10-01 post-release audit-lite
|
|
433
547
|
(findings AL-001 – AL-004): CLI owning-process startup recovery so an interrupted
|
|
@@ -439,8 +553,8 @@ that precede it. The v0.1.7 source candidate was verified with real CLI, HTTP an
|
|
|
439
553
|
MCP speech, seven-format exports and completed resume; the v0.1.8 runtime fixes
|
|
440
554
|
were independently checked through fresh-process CLI restart probes, real SQLite
|
|
441
555
|
setup-failure tests, and the full Windows test suite. Those checks are not new
|
|
442
|
-
individual-harness receipts. That is the previous
|
|
443
|
-
for v0.1.
|
|
556
|
+
individual-harness receipts. That is the previous releases' record, not evidence
|
|
557
|
+
for v0.1.11.
|
|
444
558
|
|
|
445
559
|
The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
|
|
446
560
|
for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
|
|
@@ -459,7 +573,7 @@ and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
|
|
|
459
573
|
[fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
|
|
460
574
|
live — that is the v0.1.6 release's evidence, not a receipt for a later release.
|
|
461
575
|
Everything from here to the end of this section is the v0.1.6 release's
|
|
462
|
-
historical record as published: it is not re-verified for v0.1.
|
|
576
|
+
historical record as published: it is not re-verified for v0.1.11, whose separate release evidence is not supplied by these historical paragraphs.
|
|
463
577
|
Merged-main CI passed 16/16 on the tagged commit; the published wheel and
|
|
464
578
|
sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
|
|
465
579
|
Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
|
|
@@ -8,7 +8,7 @@ Cross-platform media transcription toolkit. **One core, one CLI, thin adapters.*
|
|
|
8
8
|
[User manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md) ·
|
|
9
9
|
[Developer and integration manual](https://github.com/scottconverse/textflowkit/blob/main/docs/adapters.md)
|
|
10
10
|
|
|
11
|
-
**Current release: [v0.1.
|
|
11
|
+
**Current release: [v0.1.11](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.11).**
|
|
12
12
|
|
|
13
13
|
The [static site deployment](https://github.com/scottconverse/textflowkit/blob/main/docs/site-deployment.md) is hosted on Cloudflare
|
|
14
14
|
Pages. GitHub remains the source and CI host; the website does not run the
|
|
@@ -69,10 +69,11 @@ DOCX and PDF are available through the optional `export` extra.
|
|
|
69
69
|
|
|
70
70
|
## Architecture
|
|
71
71
|
|
|
72
|
-

|
|
73
73
|
|
|
74
|
-
The design principle is **one
|
|
75
|
-
the core; the interfaces are thin
|
|
74
|
+
The design principle is **one shared core, thin doors**. Everything of substance
|
|
75
|
+
lives in the core; the interfaces are thin — the local browser UI is a fifth door
|
|
76
|
+
that adds only transport over the existing HTTP app and shared job store.
|
|
76
77
|
|
|
77
78
|
| Layer | Path | Responsibility |
|
|
78
79
|
|---|---|---|
|
|
@@ -82,6 +83,7 @@ the core; the interfaces are thin.
|
|
|
82
83
|
| **CLI** | `src/textflowkit/cli.py` | Reference interface (subprocess-friendly) |
|
|
83
84
|
| **MCP** | `src/textflowkit/adapters/mcp_server.py` | stdio + Streamable HTTP, for AI harnesses |
|
|
84
85
|
| **HTTP** | `src/textflowkit/adapters/http_server.py` | JSON API, for software products and web frontends |
|
|
86
|
+
| **Local UI** | `src/textflowkit/ui` | Loopback-only browser workspace over the same HTTP app and job store |
|
|
85
87
|
|
|
86
88
|
Because the core owns the pipeline, adding a door is cheap — and adding a platform
|
|
87
89
|
means writing one source adapter, not another tool.
|
|
@@ -89,6 +91,32 @@ means writing one source adapter, not another tool.
|
|
|
89
91
|
For the job lifecycle, process ownership, checkpoints, and output publication,
|
|
90
92
|
see [docs/architecture.md](https://github.com/scottconverse/textflowkit/blob/main/docs/architecture.md).
|
|
91
93
|
|
|
94
|
+
## Live microphone streaming (opt-in)
|
|
95
|
+
|
|
96
|
+
In v0.1.11, live streaming supports **Windows x86_64 only**. When
|
|
97
|
+
`TEXTFLOWKIT_STREAMING=1` is set, the developer HTTP app serves a `/stream`
|
|
98
|
+
WebSocket and the local UI serves `/api/stream`, both transcribing a live microphone
|
|
99
|
+
as you speak. A **runnable, self-hosted browser example** ships at
|
|
100
|
+
`/streaming-example` (and `/api/streaming-example` under the UI): it captures with an
|
|
101
|
+
`AudioWorklet`, resamples any device rate to 16 kHz mono, and shows the transcript.
|
|
102
|
+
No CDN, no analytics, no external fetch. Requires the `streaming` extra:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
python -m pip install "textflowkit[streaming]==0.1.11"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
It is **off by default** — with the switch unset the endpoint does not exist — and
|
|
109
|
+
**loopback-only**: auth is fail-closed, so the UI accepts only its own origin and
|
|
110
|
+
capability, the standalone API requires `TEXTFLOWKIT_API_TOKEN` (even in developer
|
|
111
|
+
mode), and a separate origin — including the standalone browser example's own origin —
|
|
112
|
+
may stream only if listed in `TEXTFLOWKIT_STREAMING_ORIGINS`. The standalone
|
|
113
|
+
`textflowkit` CLI is unaffected: it does not open a microphone or a streaming socket.
|
|
114
|
+
**Bounded live runs are verified on the native engine here** — 65 s and 300 s
|
|
115
|
+
end-to-end on Windows x86_64; the transport and the browser resampler are covered by
|
|
116
|
+
tests, and a physical browser microphone has not yet been captured (the browser proof
|
|
117
|
+
drives the page against a fake audio device). See
|
|
118
|
+
[docs/streaming.md](https://github.com/scottconverse/textflowkit/blob/main/docs/streaming.md).
|
|
119
|
+
|
|
92
120
|
## Recognized sources
|
|
93
121
|
|
|
94
122
|
YouTube · TikTok · Facebook · Instagram · Vimeo · Twitch · Bilibili · Rumble ·
|
|
@@ -235,7 +263,7 @@ textflowkit export ./transcript.json --format vtt
|
|
|
235
263
|
needs no PyTorch, so a fresh `pip install textflowkit` stays small and pulls no
|
|
236
264
|
torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
237
265
|
|
|
238
|
-
, each core runs as one owned child with forced telemetry-off flags, a partial checkpoint is written after each core, and a resume validates the source and decoded-WAV hashes then re-runs only the unfinished cores.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.11/docs/assets/whistle-resume.svg)
|
|
239
267
|
|
|
240
268
|
- **CPU only, no torch.** It runs a pinned native binary and downloads one pinned
|
|
241
269
|
model on first use. Naming a GPU device is refused rather than silently
|
|
@@ -252,7 +280,7 @@ torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
|
252
280
|
of context on each side, so every standalone clip is ≤ 30 seconds (the native
|
|
253
281
|
CLI's limit). Overlap words are selected by core midpoint rather than text
|
|
254
282
|
deduplication, so repeated spoken phrases are preserved.
|
|
255
|
-
- **
|
|
283
|
+
- **Standalone streaming is not used.** The native `--audio-stream` mode failed its
|
|
256
284
|
coverage and is never passed; only the committed standalone output is parsed.
|
|
257
285
|
- **Durable block resume.** With `TEXTFLOWKIT_DB` set, a long run writes partial
|
|
258
286
|
per-block checkpoints; a resume checks the source and decoded-WAV hashes and the
|
|
@@ -338,6 +366,66 @@ contract checks cover it, and running an actual build is deliberately out of
|
|
|
338
366
|
scope here, so no image is claimed to build or start. See
|
|
339
367
|
[the container example](https://github.com/scottconverse/textflowkit/blob/main/docs/adapters.md#container-example-dockerfile-and-compose).
|
|
340
368
|
|
|
369
|
+
## Local browser interface
|
|
370
|
+
|
|
371
|
+
For point-and-click use there is a local browser workspace that runs on **this
|
|
372
|
+
machine only**, reuses the same pipeline and job store, and adds no dependency of
|
|
373
|
+
its own beyond the `http` extra. It ships with the core package as of v0.1.10:
|
|
374
|
+
a regular install of the current release carries it.
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
python -m pip install 'textflowkit[http,export]==0.1.11'
|
|
378
|
+
textflowkit-ui
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
On Windows you can create a desktop shortcut when you want one:
|
|
382
|
+
|
|
383
|
+
```powershell
|
|
384
|
+
textflowkit-ui --create-shortcut # Start Menu entry (pythonw, no console)
|
|
385
|
+
textflowkit-ui --create-shortcut --shortcut-dir 'C:\path\to\folder'
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
The shortcut is created only on request and needs no `pywin32`. Under `pythonw`
|
|
389
|
+
there is no console, so a startup failure is written to a log file under the
|
|
390
|
+
per-user data directory and shown in a message box rather than failing silently.
|
|
391
|
+
The normal operator path is to launch from that shortcut; the console command
|
|
392
|
+
above is equivalent.
|
|
393
|
+
|
|
394
|
+
**This is a local app, not a public website.** The [landing page](https://www.textflowkit.org/)
|
|
395
|
+
is static documentation served by Cloudflare Pages; it does **not** run the
|
|
396
|
+
transcription engine and offers no upload form. The browser workspace exists only
|
|
397
|
+
on the machine that installed it.
|
|
398
|
+
|
|
399
|
+
- **Loopback only.** It binds `127.0.0.1` (never off the machine, whatever
|
|
400
|
+
`TEXTFLOWKIT_ALLOW_REMOTE` is set to) and opens a browser once it is serving.
|
|
401
|
+
- **One owner per database.** A second launch against the same database opens the
|
|
402
|
+
UI already running rather than starting a competing server. **Stop server** in
|
|
403
|
+
the workspace shuts the local server down without a terminal, waiting for the
|
|
404
|
+
current jobs to finish rather than interrupting them. Shutdown **drains** — it
|
|
405
|
+
lets in-flight jobs complete; it does **not** auto-cancel them. Cancel a job
|
|
406
|
+
first to stop it early.
|
|
407
|
+
- **Durable jobs with cancel and resume.** Jobs and checkpoints are stored
|
|
408
|
+
durably under the per-user data directory unless you set `TEXTFLOWKIT_DB` /
|
|
409
|
+
`TEXTFLOWKIT_WORK_ROOT` / `TEXTFLOWKIT_OUTPUT_ROOT`. A dropped file is capped
|
|
410
|
+
at **2 GiB** by default (`TEXTFLOWKIT_UI_MAX_UPLOAD_BYTES` overrides it).
|
|
411
|
+
In-workspace playback uses the browser's native player on the **currently
|
|
412
|
+
selected** media, so it depends on what that browser can decode; it is a
|
|
413
|
+
convenience preview, not a format guarantee.
|
|
414
|
+
- **No UI analytics.** The page loads no CDN asset and no analytics, and the
|
|
415
|
+
session token lives only in the page — never in a URL, cookie, or log line.
|
|
416
|
+
- **What uses the network.** The page itself loads nothing remote. A **URL
|
|
417
|
+
source** is downloaded from the internet; an engine's **model** may be
|
|
418
|
+
downloaded on first use; and **remote or cloud translation** (an advanced
|
|
419
|
+
option) sends transcript text to that backend. With local media and a local
|
|
420
|
+
translation model, no transcript leaves the machine.
|
|
421
|
+
- `--port`, `--no-browser`, and `--version` are available.
|
|
422
|
+
|
|
423
|
+
The other doors are unchanged: the CLI, Python API, MCP, and HTTP adapters keep
|
|
424
|
+
their existing behavior, and the optional engines, diarization, and translation
|
|
425
|
+
retain their documented dependency requirements. See the
|
|
426
|
+
[user manual](https://github.com/scottconverse/textflowkit/blob/main/docs/user-manual.md#7-local-browser-interface)
|
|
427
|
+
and [architecture guide](https://github.com/scottconverse/textflowkit/blob/main/docs/architecture.md#one-owner-per-database).
|
|
428
|
+
|
|
341
429
|
## Durable, bounded, cancellable
|
|
342
430
|
|
|
343
431
|
```bash
|
|
@@ -352,23 +440,43 @@ boundary. See [docs/adapters.md](https://github.com/scottconverse/textflowkit/bl
|
|
|
352
440
|
|
|
353
441
|
The MCP and HTTP adapters are **job-based**: submission returns a job id
|
|
354
442
|
immediately and clients poll for completion. The CLI uses the same core but
|
|
355
|
-
waits for the result. This lets AI harnesses, software products, and
|
|
356
|
-
|
|
443
|
+
waits for the result. This lets AI harnesses, software products, and the local
|
|
444
|
+
browser interface share the job contract without blocking a request.
|
|
357
445
|
|
|
358
446
|
## Status
|
|
359
447
|
|
|
360
|
-
**v0.1.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
`
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
448
|
+
**v0.1.11 release.** Optional live streaming adds a transport-neutral
|
|
449
|
+
`StreamingSession` Python API, incremental transcript events, and authenticated
|
|
450
|
+
loopback WebSockets (`/stream` on the developer HTTP API and `/api/stream` on the
|
|
451
|
+
local UI), with a packaged browser microphone example. The native live capability
|
|
452
|
+
supports **Windows x86_64 only** and uses one owned child with a separately pinned
|
|
453
|
+
`libneedle3.dll`. The `streaming` extra supplies the WebSocket dependency;
|
|
454
|
+
`TEXTFLOWKIT_STREAMING=1` enables the server routes. Streaming is off by default.
|
|
455
|
+
|
|
456
|
+
Existing file and URL transcription, CLI, MCP, durable jobs, and local browser
|
|
457
|
+
workspace defaults remain unchanged. Whistle stays the CPU-only standalone default;
|
|
458
|
+
`openai-whisper` remains an explicit opt-in engine. The local browser workspace
|
|
459
|
+
introduced in v0.1.10 still needs only the `http` extra for its ordinary job flow.
|
|
460
|
+
Fonts remain 0.1.6. Live sessions are ephemeral and have no durable resume.
|
|
461
|
+
|
|
462
|
+
**Streaming evidence.** Local English PCM runs exercised the native core for 65 s
|
|
463
|
+
and 300 s; a separate assembled UI WebSocket run fed prerecorded PCM at real time
|
|
464
|
+
for 12 s and returned incremental events and a final transcript. Browser lifecycle
|
|
465
|
+
and resampling checks used fake audio. Physical browser microphone capture, live
|
|
466
|
+
Linux/macOS, and the six other accepted languages were not verified. The public
|
|
467
|
+
website remains static documentation and serves no streaming endpoint. Local source
|
|
468
|
+
validation does not establish published-package or exact-commit CI results.
|
|
469
|
+
|
|
470
|
+
**Verification limit.** The local browser interface is covered by an automated
|
|
471
|
+
suite, and the UI's behavior was proved on a **native Windows** machine in a real
|
|
472
|
+
browser. No live optional-backend (translation/diarization) run through the UI is
|
|
473
|
+
claimed, and **no live Linux or macOS UI run was performed here** — those
|
|
474
|
+
platforms are covered by automated tests only, and CI across Windows, Linux, and
|
|
475
|
+
macOS is a separate release gate. Release publication uses the tag
|
|
476
|
+
workflow, which requires successful exact-commit main CI before PyPI uploads and
|
|
477
|
+
creates the public GitHub release only afterward. Check the linked release for
|
|
478
|
+
artifacts and workflow status; local source verification is not a fresh
|
|
479
|
+
PyPI-install or individual-harness receipt.
|
|
372
480
|
|
|
373
481
|
The v0.1.8 release carried four fixes for the 2026-10-01 post-release audit-lite
|
|
374
482
|
(findings AL-001 – AL-004): CLI owning-process startup recovery so an interrupted
|
|
@@ -380,8 +488,8 @@ that precede it. The v0.1.7 source candidate was verified with real CLI, HTTP an
|
|
|
380
488
|
MCP speech, seven-format exports and completed resume; the v0.1.8 runtime fixes
|
|
381
489
|
were independently checked through fresh-process CLI restart probes, real SQLite
|
|
382
490
|
setup-failure tests, and the full Windows test suite. Those checks are not new
|
|
383
|
-
individual-harness receipts. That is the previous
|
|
384
|
-
for v0.1.
|
|
491
|
+
individual-harness receipts. That is the previous releases' record, not evidence
|
|
492
|
+
for v0.1.11.
|
|
385
493
|
|
|
386
494
|
The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
|
|
387
495
|
for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
|
|
@@ -400,7 +508,7 @@ and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
|
|
|
400
508
|
[fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
|
|
401
509
|
live — that is the v0.1.6 release's evidence, not a receipt for a later release.
|
|
402
510
|
Everything from here to the end of this section is the v0.1.6 release's
|
|
403
|
-
historical record as published: it is not re-verified for v0.1.
|
|
511
|
+
historical record as published: it is not re-verified for v0.1.11, whose separate release evidence is not supplied by these historical paragraphs.
|
|
404
512
|
Merged-main CI passed 16/16 on the tagged commit; the published wheel and
|
|
405
513
|
sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
|
|
406
514
|
Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
|