textflowkit 0.1.10__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.10 → textflowkit-0.1.11}/CHANGELOG.md +38 -1
- {textflowkit-0.1.10 → textflowkit-0.1.11}/CONTRIBUTING.md +7 -1
- {textflowkit-0.1.10 → textflowkit-0.1.11}/PKG-INFO +62 -25
- {textflowkit-0.1.10 → textflowkit-0.1.11}/README.md +55 -24
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/adapters.md +45 -3
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/architecture.md +27 -1
- textflowkit-0.1.11/docs/assets/live-streaming-flow.svg +50 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/index.html +12 -7
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/install.md +21 -2
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/release-checklist.md +25 -1
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/roadmap.md +16 -1
- textflowkit-0.1.11/docs/streaming.md +514 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/user-manual.md +43 -8
- {textflowkit-0.1.10 → textflowkit-0.1.11}/pyproject.toml +8 -2
- textflowkit-0.1.11/src/textflowkit/__init__.py +41 -0
- {textflowkit-0.1.10 → 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.10 → textflowkit-0.1.11}/src/textflowkit/ui/app.py +134 -2
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/launcher.py +25 -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/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.10 → textflowkit-0.1.11}/tests/test_ui_packaging.py +13 -2
- textflowkit-0.1.10/src/textflowkit/__init__.py +0 -8
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.dockerignore +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.env.example +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.gitattributes +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.github/dependabot.yml +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.github/workflows/ci.yml +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.github/workflows/publish-pypi.yml +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.gitignore +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/.pre-commit-config.yaml +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/Dockerfile +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/LEGAL.md +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/LICENSE +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/SECURITY.md +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/compose.yaml +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/.nojekyll +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/404.html +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/assets/architecture-overview.svg +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/assets/local-ui-flow.svg +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/assets/whistle-resume.svg +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/site-deployment.md +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/docs/sources.md +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/fetch_published_fonts.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/smoke_installed_wheel.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/smoke_live_youtube.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/verify_readme_release.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/verify_release_ci.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/verify_release_versions.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/scripts/write_release_manifest.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/adapters/__init__.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/adapters/mcp_server.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/assets/README.md +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/assets/selftest-speech.wav +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/cli.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/__init__.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/batch.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/bind.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/cancel.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/checkpoint.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/diarize.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/engine.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/executor.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/jobs.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/model.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/paths.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/pipeline.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/retrieval.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/runner.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/service.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/sqlite_store.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/startup.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/submission.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/timeutil.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/translate.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/whistle.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/core/whistle_assets.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/__init__.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/_cue_layout.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/_cue_text.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/_rename_excl.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/_rename_noreplace.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/docx.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/markdown.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/pdf.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/srt.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/txt.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/render/vtt.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/sources/__init__.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/sources/acquire.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/sources/detect.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/sources/scratch.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/__init__.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/capabilities.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/ownership.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/paths.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/security.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/static/app.css +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/static/app.js +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/static/index.html +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/src/textflowkit/ui/uploads.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/__init__.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/ollama_stub.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_acquire.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_adapters.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_admission_ownership.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_atomic_resume.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_atomic_resume_aba.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_batch.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_batch_item_boundary.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_batch_resume_shared.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_bind.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cancellation_finalization.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_checkpoint.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_checkpoint_single_copy.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cli.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cli_batch_feedback.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cli_owning_recovery.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cli_resume_batch.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cli_stage_feedback.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cli_stdout_format.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_confined_decoder_boundary.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_confined_indirect_media.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_confined_resume_boundary.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_container_example.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_cue_layout.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_diarize.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_diarize_example_flags.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_diarize_token_docs.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_docx_publication_identity.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_done_output_integrity.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_empty_formats_resume.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_engine_adapters.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_engine_cache.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_engine_faster.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_engine_quiet.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_executor.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_executor_store_failure.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_export.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_export_file_mode.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_export_preflight.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_faster_whisper_docs.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_fetch_published_fonts.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_font_notices.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_http_host_boundary.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_http_trusted_proxy.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_job_progress.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_jobs.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_landing_commands.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_landing_page.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_legal_summary.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_linux_no_hardlink.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_live_smoke_script.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_macos_no_hardlink.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_mcp_batch_cookie_docs.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_mcp_http_boundary.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_mcp_protocol_cleanliness.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_mcp_terminal_guidance.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_mcp_tool_descriptions.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_mcp_work_root.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_model.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_partial_output_resume.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_partial_pdf_resume.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_paths.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_pipeline_integrity.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_pipeline_resume_setup.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_production_browser_cookies.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_publish_ci_gate.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_publish_fonts_wiring.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_publish_manifest_wiring.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_publish_workflow_gate.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_readme_layout.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_readme_release_guard.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_release_boundaries.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_release_manifest.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_release_surfaces.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_render.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_retrieval.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_sdist_allowlist.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_service_profile.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_site_not_found.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_sources.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_stage_reuse_resume.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_startup_recovery.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_stdio_protocol.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_submission.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_submission_validation.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_translate.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_translate_completeness.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_assets_and_capabilities.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_consoleless_logging.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_existing_routes_unchanged.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_launcher.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_ownership_and_shutdown.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_real_serve.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_security.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_submission_and_download.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_ui_uploads.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_verify_release_versions.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_whistle_assets.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_whistle_defaults.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_whistle_engine.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_whistle_job_resume.py +0 -0
- {textflowkit-0.1.10 → textflowkit-0.1.11}/tests/test_windows_no_hardlink.py +0 -0
|
@@ -1,5 +1,42 @@
|
|
|
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
|
+
|
|
3
40
|
## v0.1.10 — 2026-10-06
|
|
4
41
|
|
|
5
42
|
**The local browser interface ships.** The loopback-only browser workspace
|
|
@@ -51,7 +88,7 @@ security boundaries. A **native Windows** machine, in a real browser, proved the
|
|
|
51
88
|
workspace end to end (drop a file, submit, download, stop). That is one platform's
|
|
52
89
|
browser proof, **not** a live Linux or macOS UI run — those platforms are covered
|
|
53
90
|
by automated tests only, and cross-platform CI (Windows/Linux/macOS) is a separate
|
|
54
|
-
|
|
91
|
+
release gate. **No live optional-backend (translation or
|
|
55
92
|
diarization) run through the UI is claimed.** The engine and packaging changes of
|
|
56
93
|
v0.1.9 are unchanged by this release.
|
|
57
94
|
|
|
@@ -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,7 +134,7 @@ DOCX and PDF are available through the optional `export` extra.
|
|
|
128
134
|
|
|
129
135
|
## Architecture
|
|
130
136
|
|
|
131
|
-
 sit above one core that acquires and decodes media, transcribes with the default Whistle engine or an explicitly selected openai-whisper, keeps job state and resume checkpoints in an optional SQLite store, adds optional speaker or translation postprocessing, and publishes TXT, SRT, VTT, JSON, Markdown, and optional DOCX/PDF exports.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.11/docs/assets/architecture-overview.svg)
|
|
132
138
|
|
|
133
139
|
The design principle is **one shared core, thin doors**. Everything of substance
|
|
134
140
|
lives in the core; the interfaces are thin — the local browser UI is a fifth door
|
|
@@ -150,6 +156,32 @@ means writing one source adapter, not another tool.
|
|
|
150
156
|
For the job lifecycle, process ownership, checkpoints, and output publication,
|
|
151
157
|
see [docs/architecture.md](https://github.com/scottconverse/textflowkit/blob/main/docs/architecture.md).
|
|
152
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
|
+
|
|
153
185
|
## Recognized sources
|
|
154
186
|
|
|
155
187
|
YouTube · TikTok · Facebook · Instagram · Vimeo · Twitch · Bilibili · Rumble ·
|
|
@@ -296,7 +328,7 @@ textflowkit export ./transcript.json --format vtt
|
|
|
296
328
|
needs no PyTorch, so a fresh `pip install textflowkit` stays small and pulls no
|
|
297
329
|
torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
298
330
|
|
|
299
|
-
, 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)
|
|
300
332
|
|
|
301
333
|
- **CPU only, no torch.** It runs a pinned native binary and downloads one pinned
|
|
302
334
|
model on first use. Naming a GPU device is refused rather than silently
|
|
@@ -313,7 +345,7 @@ torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
|
313
345
|
of context on each side, so every standalone clip is ≤ 30 seconds (the native
|
|
314
346
|
CLI's limit). Overlap words are selected by core midpoint rather than text
|
|
315
347
|
deduplication, so repeated spoken phrases are preserved.
|
|
316
|
-
- **
|
|
348
|
+
- **Standalone streaming is not used.** The native `--audio-stream` mode failed its
|
|
317
349
|
coverage and is never passed; only the committed standalone output is parsed.
|
|
318
350
|
- **Durable block resume.** With `TEXTFLOWKIT_DB` set, a long run writes partial
|
|
319
351
|
per-block checkpoints; a resume checks the source and decoded-WAV hashes and the
|
|
@@ -407,7 +439,7 @@ its own beyond the `http` extra. It ships with the core package as of v0.1.10:
|
|
|
407
439
|
a regular install of the current release carries it.
|
|
408
440
|
|
|
409
441
|
```bash
|
|
410
|
-
python -m pip install 'textflowkit[http,export]==0.1.
|
|
442
|
+
python -m pip install 'textflowkit[http,export]==0.1.11'
|
|
411
443
|
textflowkit-ui
|
|
412
444
|
```
|
|
413
445
|
|
|
@@ -478,29 +510,34 @@ browser interface share the job contract without blocking a request.
|
|
|
478
510
|
|
|
479
511
|
## Status
|
|
480
512
|
|
|
481
|
-
**v0.1.
|
|
482
|
-
|
|
483
|
-
(`
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
`
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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.
|
|
497
534
|
|
|
498
535
|
**Verification limit.** The local browser interface is covered by an automated
|
|
499
536
|
suite, and the UI's behavior was proved on a **native Windows** machine in a real
|
|
500
537
|
browser. No live optional-backend (translation/diarization) run through the UI is
|
|
501
538
|
claimed, and **no live Linux or macOS UI run was performed here** — those
|
|
502
539
|
platforms are covered by automated tests only, and CI across Windows, Linux, and
|
|
503
|
-
macOS is
|
|
540
|
+
macOS is a separate release gate. Release publication uses the tag
|
|
504
541
|
workflow, which requires successful exact-commit main CI before PyPI uploads and
|
|
505
542
|
creates the public GitHub release only afterward. Check the linked release for
|
|
506
543
|
artifacts and workflow status; local source verification is not a fresh
|
|
@@ -517,7 +554,7 @@ MCP speech, seven-format exports and completed resume; the v0.1.8 runtime fixes
|
|
|
517
554
|
were independently checked through fresh-process CLI restart probes, real SQLite
|
|
518
555
|
setup-failure tests, and the full Windows test suite. Those checks are not new
|
|
519
556
|
individual-harness receipts. That is the previous releases' record, not evidence
|
|
520
|
-
for v0.1.
|
|
557
|
+
for v0.1.11.
|
|
521
558
|
|
|
522
559
|
The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
|
|
523
560
|
for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
|
|
@@ -536,7 +573,7 @@ and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
|
|
|
536
573
|
[fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
|
|
537
574
|
live — that is the v0.1.6 release's evidence, not a receipt for a later release.
|
|
538
575
|
Everything from here to the end of this section is the v0.1.6 release's
|
|
539
|
-
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.
|
|
540
577
|
Merged-main CI passed 16/16 on the tagged commit; the published wheel and
|
|
541
578
|
sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
|
|
542
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,7 +69,7 @@ DOCX and PDF are available through the optional `export` extra.
|
|
|
69
69
|
|
|
70
70
|
## Architecture
|
|
71
71
|
|
|
72
|
-
 sit above one core that acquires and decodes media, transcribes with the default Whistle engine or an explicitly selected openai-whisper, keeps job state and resume checkpoints in an optional SQLite store, adds optional speaker or translation postprocessing, and publishes TXT, SRT, VTT, JSON, Markdown, and optional DOCX/PDF exports.](https://raw.githubusercontent.com/scottconverse/textflowkit/v0.1.11/docs/assets/architecture-overview.svg)
|
|
73
73
|
|
|
74
74
|
The design principle is **one shared core, thin doors**. Everything of substance
|
|
75
75
|
lives in the core; the interfaces are thin — the local browser UI is a fifth door
|
|
@@ -91,6 +91,32 @@ means writing one source adapter, not another tool.
|
|
|
91
91
|
For the job lifecycle, process ownership, checkpoints, and output publication,
|
|
92
92
|
see [docs/architecture.md](https://github.com/scottconverse/textflowkit/blob/main/docs/architecture.md).
|
|
93
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
|
+
|
|
94
120
|
## Recognized sources
|
|
95
121
|
|
|
96
122
|
YouTube · TikTok · Facebook · Instagram · Vimeo · Twitch · Bilibili · Rumble ·
|
|
@@ -237,7 +263,7 @@ textflowkit export ./transcript.json --format vtt
|
|
|
237
263
|
needs no PyTorch, so a fresh `pip install textflowkit` stays small and pulls no
|
|
238
264
|
torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
239
265
|
|
|
240
|
-
, 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)
|
|
241
267
|
|
|
242
268
|
- **CPU only, no torch.** It runs a pinned native binary and downloads one pinned
|
|
243
269
|
model on first use. Naming a GPU device is refused rather than silently
|
|
@@ -254,7 +280,7 @@ torch; `openai-whisper` is an explicitly selectable opt-in engine.
|
|
|
254
280
|
of context on each side, so every standalone clip is ≤ 30 seconds (the native
|
|
255
281
|
CLI's limit). Overlap words are selected by core midpoint rather than text
|
|
256
282
|
deduplication, so repeated spoken phrases are preserved.
|
|
257
|
-
- **
|
|
283
|
+
- **Standalone streaming is not used.** The native `--audio-stream` mode failed its
|
|
258
284
|
coverage and is never passed; only the committed standalone output is parsed.
|
|
259
285
|
- **Durable block resume.** With `TEXTFLOWKIT_DB` set, a long run writes partial
|
|
260
286
|
per-block checkpoints; a resume checks the source and decoded-WAV hashes and the
|
|
@@ -348,7 +374,7 @@ its own beyond the `http` extra. It ships with the core package as of v0.1.10:
|
|
|
348
374
|
a regular install of the current release carries it.
|
|
349
375
|
|
|
350
376
|
```bash
|
|
351
|
-
python -m pip install 'textflowkit[http,export]==0.1.
|
|
377
|
+
python -m pip install 'textflowkit[http,export]==0.1.11'
|
|
352
378
|
textflowkit-ui
|
|
353
379
|
```
|
|
354
380
|
|
|
@@ -419,29 +445,34 @@ browser interface share the job contract without blocking a request.
|
|
|
419
445
|
|
|
420
446
|
## Status
|
|
421
447
|
|
|
422
|
-
**v0.1.
|
|
423
|
-
|
|
424
|
-
(`
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
`
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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.
|
|
438
469
|
|
|
439
470
|
**Verification limit.** The local browser interface is covered by an automated
|
|
440
471
|
suite, and the UI's behavior was proved on a **native Windows** machine in a real
|
|
441
472
|
browser. No live optional-backend (translation/diarization) run through the UI is
|
|
442
473
|
claimed, and **no live Linux or macOS UI run was performed here** — those
|
|
443
474
|
platforms are covered by automated tests only, and CI across Windows, Linux, and
|
|
444
|
-
macOS is
|
|
475
|
+
macOS is a separate release gate. Release publication uses the tag
|
|
445
476
|
workflow, which requires successful exact-commit main CI before PyPI uploads and
|
|
446
477
|
creates the public GitHub release only afterward. Check the linked release for
|
|
447
478
|
artifacts and workflow status; local source verification is not a fresh
|
|
@@ -458,7 +489,7 @@ MCP speech, seven-format exports and completed resume; the v0.1.8 runtime fixes
|
|
|
458
489
|
were independently checked through fresh-process CLI restart probes, real SQLite
|
|
459
490
|
setup-failure tests, and the full Windows test suite. Those checks are not new
|
|
460
491
|
individual-harness receipts. That is the previous releases' record, not evidence
|
|
461
|
-
for v0.1.
|
|
492
|
+
for v0.1.11.
|
|
462
493
|
|
|
463
494
|
The v0.1.6 release was the post-v0.1.5 review repair set: security hardening
|
|
464
495
|
for media acquisition and the HTTP and MCP adapters, safer subtitle wrapping and
|
|
@@ -477,7 +508,7 @@ and both [core](https://pypi.org/project/textflowkit/0.1.6/) and
|
|
|
477
508
|
[fonts](https://pypi.org/project/textflowkit-fonts/0.1.6/) PyPI projects are
|
|
478
509
|
live — that is the v0.1.6 release's evidence, not a receipt for a later release.
|
|
479
510
|
Everything from here to the end of this section is the v0.1.6 release's
|
|
480
|
-
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.
|
|
481
512
|
Merged-main CI passed 16/16 on the tagged commit; the published wheel and
|
|
482
513
|
sdist digests match the GitHub release assets and their SHA-256 list; and a fresh
|
|
483
514
|
Windows Python 3.12 install of `textflowkit[export,mcp,http]==0.1.6` from PyPI
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Developer and integration manual
|
|
2
2
|
|
|
3
|
-
Current release: [v0.1.
|
|
3
|
+
Current release: [v0.1.11](https://github.com/scottconverse/textflowkit/releases/tag/v0.1.11).
|
|
4
4
|
Start with the [user manual](user-manual.md) for everyday use. Harness versions
|
|
5
5
|
in the compatibility table below identify **historical test sessions**, not
|
|
6
6
|
the version of TextFlowKit currently published.
|
|
@@ -8,7 +8,8 @@ the version of TextFlowKit currently published.
|
|
|
8
8
|
textflowkit has one core and several thin doors. Nothing is duplicated between
|
|
9
9
|
them: the CLI, the MCP server, the HTTP API, and the local browser
|
|
10
10
|
interface (`textflowkit-ui`) all call `textflowkit.core.submission` and share one
|
|
11
|
-
job model.
|
|
11
|
+
job model for file and URL transcription. The optional live `StreamingSession`
|
|
12
|
+
API and WebSockets are ephemeral and bypass durable job submission.
|
|
12
13
|
|
|
13
14
|

|
|
14
15
|
|
|
@@ -506,6 +507,47 @@ agree. So if you do leave it on, put it behind a proxy that appends its own
|
|
|
506
507
|
observation rather than forwarding the caller's header, and keep
|
|
507
508
|
`FORWARDED_ALLOW_IPS` narrow.
|
|
508
509
|
|
|
510
|
+
## Live microphone streaming (`/stream`, opt-in)
|
|
511
|
+
|
|
512
|
+
In v0.1.11, native live streaming supports **Windows x86_64 only**. Other live
|
|
513
|
+
platforms are unsupported; existing standalone defaults and platform support are
|
|
514
|
+
unchanged. Physical browser microphone capture was not verified. The public site
|
|
515
|
+
is static documentation and serves no streams. Both local server surfaces can
|
|
516
|
+
carry a live microphone stream when
|
|
517
|
+
`TEXTFLOWKIT_STREAMING=1` is set: the developer HTTP app at `/stream`, and the UI at
|
|
518
|
+
`/api/stream`. It is **off by default** - with the switch unset the route does not
|
|
519
|
+
exist and a connection is refused before any session is allocated - and it needs the
|
|
520
|
+
`streaming` extra (`websockets`).
|
|
521
|
+
|
|
522
|
+
```powershell
|
|
523
|
+
python -m pip install "textflowkit[streaming]==0.1.11"
|
|
524
|
+
# Native Windows PowerShell:
|
|
525
|
+
$env:TEXTFLOWKIT_API_TOKEN="choose-a-long-random-token"
|
|
526
|
+
$env:TEXTFLOWKIT_STREAMING="1"
|
|
527
|
+
textflowkit-http --streaming # ws://127.0.0.1:8767/stream
|
|
528
|
+
# or the documented import target directly - the WS bounds are NOT automatic here,
|
|
529
|
+
# the plain uvicorn line above would keep uvicorn's larger defaults and deflate on:
|
|
530
|
+
uvicorn textflowkit.adapters.http_server:app --host 127.0.0.1 --port 8767 `
|
|
531
|
+
--ws-max-size 32768 --ws-max-queue 5 --ws-per-message-deflate false --no-proxy-headers
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
The launcher (`textflowkit-http --streaming`) applies those bounds for you; a direct
|
|
535
|
+
ASGI invocation only has them when the flags are passed. `--no-proxy-headers` keeps
|
|
536
|
+
a proxy header from rewriting the peer address the loopback check reads (the same
|
|
537
|
+
switch the proxy-identity section above discusses).
|
|
538
|
+
|
|
539
|
+
The endpoint is a plain version-1 JSON + PCM WebSocket: one `start`, binary audio
|
|
540
|
+
(16 kHz mono s16le, ≤ 32000 bytes/frame), then `finish` or `cancel`; the server sends
|
|
541
|
+
`ready`, `event`s, and exactly one terminal `final` or `error`. Sessions are
|
|
542
|
+
ephemeral - no job row, no resume, no reconnect. Auth is fail-closed and there is no
|
|
543
|
+
anonymous path: a non-browser client sends `Authorization: Bearer` (or `token` in the
|
|
544
|
+
start JSON); a browser the UI served sends the UI capability. The standalone
|
|
545
|
+
`/stream` may additionally admit exact extra origins from
|
|
546
|
+
`TEXTFLOWKIT_STREAMING_ORIGINS` (token-authenticated); the UI's own origin is never
|
|
547
|
+
widened by that list. Streaming is loopback-only even under
|
|
548
|
+
`TEXTFLOWKIT_ALLOW_REMOTE`. The full contract, lifecycle, limits, and a generic
|
|
549
|
+
integration recipe are in [streaming.md](streaming.md).
|
|
550
|
+
|
|
509
551
|
## Local browser interface (`textflowkit-ui`)
|
|
510
552
|
|
|
511
553
|
`textflowkit-ui` is a fourth thin door beside the CLI, MCP, and HTTP entry
|
|
@@ -518,7 +560,7 @@ supplies FastAPI and uvicorn, and adds no new dependency). It has no public site
|
|
|
518
560
|
of its own: it is a local app, not a hosted service.
|
|
519
561
|
|
|
520
562
|
```bash
|
|
521
|
-
python -m pip install 'textflowkit[http,export]==0.1.
|
|
563
|
+
python -m pip install 'textflowkit[http,export]==0.1.11'
|
|
522
564
|
textflowkit-ui # serve on 127.0.0.1 and open a browser
|
|
523
565
|
textflowkit-ui --no-browser --port 8901
|
|
524
566
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Architecture and job lifecycle
|
|
1
|
+
# Architecture and job lifecycle — v0.1.11
|
|
2
2
|
|
|
3
3
|
This guide describes how textflowkit is put together and how a job moves through
|
|
4
4
|
it. It is orientation for maintainers and integrators; it is not a deployment
|
|
@@ -26,6 +26,20 @@ a streamed upload, and a capability endpoint. It **ships in the core package as
|
|
|
26
26
|
of v0.1.10** and adds no new dependency beyond the `http` extra. It is a local
|
|
27
27
|
app: the published website is static documentation and never runs the pipeline.
|
|
28
28
|
|
|
29
|
+
Live streaming added in v0.1.11 is an optional **Windows x86_64 only** path:
|
|
30
|
+
`StreamingSession` drives one owned native child through direct `ctypes` bindings
|
|
31
|
+
to a separately pinned `libneedle3.dll`. Authenticated loopback WebSockets and a
|
|
32
|
+
packaged browser example sit above that core; no job row or resume is created.
|
|
33
|
+
Server routes are off unless `TEXTFLOWKIT_STREAMING=1` is set and need the
|
|
34
|
+
`streaming` extra. The existing standalone Whistle default and ordinary file/URL
|
|
35
|
+
job paths are unchanged. Physical microphone capture and live Linux/macOS were
|
|
36
|
+
not verified; the static public site does not run this path.
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
This separate live path bypasses durable job submission; the file/URL job
|
|
41
|
+
diagrams describe the existing standalone workflow.
|
|
42
|
+
|
|
29
43
|
### One owner per database
|
|
30
44
|
|
|
31
45
|
The durable SQLite store is owned by exactly one process. `textflowkit-ui`
|
|
@@ -88,8 +102,19 @@ flowchart LR
|
|
|
88
102
|
TR --> RENDER[Render and publish files]
|
|
89
103
|
RUN --> STORE
|
|
90
104
|
STORE --> READ[Shared paging and search]
|
|
105
|
+
MIC[Browser mic or programmatic client] -. opt-in .-> WS[WebSocket /stream or /api/stream]
|
|
106
|
+
WS --> SESSION[core.streaming StreamingSession]
|
|
107
|
+
SESSION --> WPROC[Owned stream_worker child, libneedle3]
|
|
108
|
+
WPROC --> SESSION
|
|
109
|
+
SESSION -. events .-> WS
|
|
91
110
|
```
|
|
92
111
|
|
|
112
|
+
Streaming is the one path that does **not** go through `core.submission`: a live
|
|
113
|
+
session is ephemeral, owns no job row, and is driven by its own transport-neutral
|
|
114
|
+
`StreamingSession`. It is off unless `TEXTFLOWKIT_STREAMING=1`. The dotted edges are
|
|
115
|
+
that opt-in, loopback-only path, running in parallel with the batch pipeline above
|
|
116
|
+
and sharing only the native engine library, never a job row.
|
|
117
|
+
|
|
93
118
|
## Components
|
|
94
119
|
|
|
95
120
|
| Component | Source | Responsibility |
|
|
@@ -106,6 +131,7 @@ flowchart LR
|
|
|
106
131
|
| Postprocessing | `core/diarize.py`, `core/translate.py` | Optional speaker assignment and translation |
|
|
107
132
|
| Output | `render/` | Human-readable formats and canonical JSON; atomic file publication |
|
|
108
133
|
| Retrieval | `core/retrieval.py` | Hidden filtering, time selection, paging, substring search |
|
|
134
|
+
| Live streaming | `core/streaming.py`, `core/stream_worker.py`, `adapters/streaming_ws.py` | Opt-in, loopback-only microphone stream: a transport-neutral session drives one owned native child over line JSON, fed by a guarded WebSocket. No job row, no resume. See [streaming.md](streaming.md). |
|
|
109
135
|
|
|
110
136
|
## Job lifecycle
|
|
111
137
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 490" width="1180" height="490" role="img" aria-labelledby="streamTitle streamDesc" font-family="Inter, ui-sans-serif, system-ui, 'Segoe UI', sans-serif">
|
|
2
|
+
<title id="streamTitle">TextFlowKit v0.1.11 optional local live streaming</title>
|
|
3
|
+
<desc id="streamDesc">Windows x86_64 only, off by default. A browser AudioWorklet or programmatic PCM client feeds signed 16-bit little-endian mono 16000 Hz audio into an authenticated loopback WebSocket: /stream on the developer HTTP API or /api/stream on the UI. Origin, Host and peer checks guard the transport. StreamingSession bounds audio backlog at five seconds and defaults to one native session per process. One owned child binds directly to a separately pinned libneedle3.dll. Incremental committed text and a replacement provisional tail return to the client. Finish flushes accepted audio and returns a canonical Transcript; cancel or disconnect cleans up the owned child. No durable job, replay or resume. Existing standalone Whistle defaults remain unchanged. The public site serves no streams; physical microphone capture was not verified.</desc>
|
|
4
|
+
<defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="#3b556e"/></marker></defs>
|
|
5
|
+
<style>
|
|
6
|
+
.title {fill:#14303f;font-size:24px;font-weight:700}
|
|
7
|
+
.head {fill:#14303f;font-size:18px;font-weight:700}
|
|
8
|
+
.body {fill:#3b556e;font-size:15px}
|
|
9
|
+
.note {fill:#5b7186;font-size:14px}
|
|
10
|
+
.edge {fill:none;stroke:#3b556e;stroke-width:2;marker-end:url(#arrow)}
|
|
11
|
+
</style>
|
|
12
|
+
<rect x="1" y="1" width="1178" height="488" rx="18" fill="#f7fafc" stroke="#d5e0e9"/>
|
|
13
|
+
<text x="30" y="42" class="title">Optional local live streaming — v0.1.11</text>
|
|
14
|
+
<text x="30" y="70" class="body">Windows x86_64 only · streaming extra + TEXTFLOWKIT_STREAMING=1 · off by default</text>
|
|
15
|
+
<rect x="30" y="105" width="250" height="150" rx="12" fill="#e0e7f8" stroke="#b8c7df"/>
|
|
16
|
+
<text x="46" y="133" class="head">Browser or PCM client</text>
|
|
17
|
+
<text x="46" y="161" class="body">AudioWorklet resampling</text>
|
|
18
|
+
<text x="46" y="186" class="body">16 kHz mono · s16le</text>
|
|
19
|
+
<text x="46" y="211" class="body">≤ 32000 bytes per frame</text>
|
|
20
|
+
<text x="46" y="236" class="body">Explicit Start / Stop / Cancel</text>
|
|
21
|
+
<path d="M 282 180 H 313" class="edge"/>
|
|
22
|
+
<rect x="315" y="105" width="250" height="150" rx="12" fill="#eef4f8" stroke="#b8c7df"/>
|
|
23
|
+
<text x="331" y="133" class="head">Loopback WebSocket</text>
|
|
24
|
+
<text x="331" y="161" class="body">/stream or /api/stream</text>
|
|
25
|
+
<text x="331" y="186" class="body">Token / UI capability auth</text>
|
|
26
|
+
<text x="331" y="211" class="body">Exact origin + Host + peer</text>
|
|
27
|
+
<text x="331" y="236" class="body">Bounded queues and sends</text>
|
|
28
|
+
<path d="M 567 180 H 598" class="edge"/>
|
|
29
|
+
<rect x="600" y="105" width="250" height="150" rx="12" fill="#dff3ea" stroke="#a6cdbc"/>
|
|
30
|
+
<text x="616" y="133" class="head">StreamingSession</text>
|
|
31
|
+
<text x="616" y="161" class="body">Transport-neutral core API</text>
|
|
32
|
+
<text x="616" y="186" class="body">≤ 5 s unprocessed audio</text>
|
|
33
|
+
<text x="616" y="211" class="body">Bounded events and history</text>
|
|
34
|
+
<text x="616" y="236" class="body">Default: 1 session / process</text>
|
|
35
|
+
<path d="M 852 180 H 883" class="edge"/>
|
|
36
|
+
<rect x="885" y="105" width="265" height="150" rx="12" fill="#dff3ea" stroke="#a6cdbc"/>
|
|
37
|
+
<text x="901" y="133" class="head">One owned native child</text>
|
|
38
|
+
<text x="901" y="161" class="body">Pinned libneedle3.dll</text>
|
|
39
|
+
<text x="901" y="186" class="body">Direct ctypes · shared model</text>
|
|
40
|
+
<text x="901" y="211" class="body">No upstream Python SDK</text>
|
|
41
|
+
<text x="901" y="236" class="body">Cleanup on cancel / disconnect</text>
|
|
42
|
+
<path d="M 1017 258 V 306 H 155 V 258" class="edge"/>
|
|
43
|
+
<rect x="235" y="284" width="700" height="39" rx="10" fill="#f7fafc"/>
|
|
44
|
+
<text x="250" y="309" class="body">Incremental events: append committed text + replace the provisional tail</text>
|
|
45
|
+
<rect x="30" y="347" width="1120" height="64" rx="12" fill="#fff8ea" stroke="#e2cc9e"/>
|
|
46
|
+
<text x="46" y="373" class="body">Finish: flush accepted PCM → canonical Transcript. Cancel / disconnect: release the owned session.</text>
|
|
47
|
+
<text x="46" y="397" class="body">Ephemeral stream: no durable job row, replay or resume. Existing standalone Whistle defaults stay unchanged.</text>
|
|
48
|
+
<text x="30" y="442" class="note">Evidence: 65 s / 300 s native core PCM runs; separate 12 s UI WebSocket PCM run. Physical mic not verified.</text>
|
|
49
|
+
<text x="30" y="466" class="note">This is a local app capability. The public website is static documentation and serves no streams.</text>
|
|
50
|
+
</svg>
|