Vo Hoang Minh commited on
Commit
88f4cf4
·
0 Parent(s):
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +25 -0
  2. .env.example +49 -0
  3. .env.local.minio.n8n.example +29 -0
  4. .github/ISSUE_TEMPLATE/bug_report.yml +70 -0
  5. .github/ISSUE_TEMPLATE/config.yml +7 -0
  6. .github/workflows/update-build-number.yml +37 -0
  7. .gitignore +4 -0
  8. CONTRIBUTING.md +158 -0
  9. Dockerfile +215 -0
  10. LICENSE +340 -0
  11. README.md +9 -0
  12. app.py +204 -0
  13. app_utils.py +136 -0
  14. build_number.txt +1 -0
  15. config.py +45 -0
  16. docker-compose.local.minio.n8n.md +317 -0
  17. docker-compose.local.minio.n8n.yml +79 -0
  18. docker-compose.md +200 -0
  19. docker-compose.yml +44 -0
  20. docs/adding_routes.md +81 -0
  21. docs/audio/concatenate.md +207 -0
  22. docs/cloud-installation/do.md +109 -0
  23. docs/cloud-installation/gcp.md +140 -0
  24. docs/code/execute/execute_python.md +174 -0
  25. docs/ffmpeg/ffmpeg_compose.md +245 -0
  26. docs/image/convert/image_to_video.md +159 -0
  27. docs/image/screenshot_webpage.md +218 -0
  28. docs/media/convert/media_convert.md +138 -0
  29. docs/media/convert/media_to_mp3.md +142 -0
  30. docs/media/cut.md +169 -0
  31. docs/media/download.md +330 -0
  32. docs/media/feedback.md +44 -0
  33. docs/media/generate_ass.md +350 -0
  34. docs/media/media_transcribe.md +270 -0
  35. docs/media/metadata.md +156 -0
  36. docs/media/silence.md +176 -0
  37. docs/s3/upload.md +66 -0
  38. docs/toolkit/authenticate.md +92 -0
  39. docs/toolkit/job_status.md +141 -0
  40. docs/toolkit/jobs_status.md +141 -0
  41. docs/toolkit/test.md +89 -0
  42. docs/video/caption_video.md +354 -0
  43. docs/video/concatenate.md +180 -0
  44. docs/video/cut.md +197 -0
  45. docs/video/split.md +173 -0
  46. docs/video/thumbnail.md +165 -0
  47. docs/video/trim.md +147 -0
  48. generate_docs.py +329 -0
  49. generate_vector.sh +20 -0
  50. local.sh +41 -0
.dockerignore ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ignore Python cache and compiled files
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+
7
+ # Ignore environment and config files
8
+ .env
9
+ .env_variables.json
10
+ .env_shell.json
11
+
12
+ # Ignore version control and editor files
13
+ .git/
14
+ .vscode/
15
+ .DS_Store
16
+
17
+ # Ignore scripts and documentation not needed in image
18
+ README.md
19
+ local.sh
20
+ generate_vector.sh
21
+ docs/
22
+
23
+ # Ignore repository/configuration files not needed in image
24
+ .github/
25
+ .gitignore
.env.example ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Production Environment Configuration
2
+ # No Code Architect Toolkit
3
+
4
+ # The name of your application.
5
+ APP_NAME=NCAToolkit
6
+
7
+ # Debug mode setting. Set to `false` for production environments.
8
+ APP_DEBUG=false
9
+
10
+ # Your app's domain or subdomain, without the 'http://' or 'https://' prefix.
11
+ APP_DOMAIN=example.com
12
+
13
+ # Full application URL is automatically configured; no modification required.
14
+ APP_URL=https://${APP_DOMAIN}
15
+
16
+ # SSL settings
17
+ SSL_EMAIL=user@example.com
18
+
19
+ # API_KEY
20
+ # Purpose: Used for API authentication.
21
+ # Requirement: Mandatory.
22
+ API_KEY=1993
23
+
24
+ # s3 Compatible Storage Env Vars
25
+ #
26
+ #S3_ACCESS_KEY=your_access_key
27
+ #S3_SECRET_KEY=your_secret_key
28
+ #S3_ENDPOINT_URL=https://your-endpoint-url
29
+ #S3_REGION=your-region
30
+ #S3_BUCKET_NAME=your-bucket-name
31
+
32
+
33
+ # Google Cloud Storage Env Variables
34
+ #
35
+ # GCP_SA_CREDENTIALS
36
+ # Purpose: The JSON credentials for the GCP Service Account.
37
+ # Requirement: Mandatory if using GCP storage.
38
+ #GCP_SA_CREDENTIALS=/path/to/your/gcp/service_account.json
39
+
40
+ # GCP_BUCKET_NAME
41
+ # Purpose: The name of the GCP storage bucket.
42
+ # Requirement: Mandatory if using GCP storage.
43
+ #GCP_BUCKET_NAME=your_gcp_bucket_name
44
+
45
+ # STORAGE_PATH
46
+ # Purpose: The base path for storage operations.
47
+ # Default: GCP
48
+ # Requirement: Optional.
49
+ #STORAGE_PATH=GCP
.env.local.minio.n8n.example ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Local Development Environment Configuration
2
+ # No Code Architect Toolkit - Local Setup with MinIO
3
+
4
+ # App Configuration
5
+ APP_NAME=NCAToolkit
6
+ APP_DEBUG=true
7
+ APP_DOMAIN=localhost:8080
8
+ APP_URL=http://localhost:8080
9
+
10
+ # API Configuration
11
+ API_KEY=local-dev-key-123
12
+
13
+ # MinIO S3-Compatible Storage Configuration
14
+ S3_ENDPOINT_URL=http://minio:9000
15
+ S3_ACCESS_KEY=minioadmin
16
+ S3_SECRET_KEY=minioadmin123
17
+ S3_REGION=us-east-1
18
+ S3_BUCKET_NAME=nca-toolkit-local
19
+
20
+ # Optional: Gunicorn Configuration
21
+ GUNICORN_WORKERS=2
22
+ GUNICORN_TIMEOUT=300
23
+
24
+ # n8n Configuration
25
+ N8N_HOST=localhost
26
+ N8N_PORT=5678
27
+ N8N_PROTOCOL=http
28
+ WEBHOOK_URL=http://localhost:5678/
29
+ GENERIC_TIMEZONE=UTC
.github/ISSUE_TEMPLATE/bug_report.yml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Bug Report
2
+ title: "[Bug]: "
3
+ labels: ["bug"]
4
+ description: Report broken or incorrect behaviour
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: >
9
+ Thanks for taking the time to fill out a bug.
10
+ Please note that this form is for bugs only!
11
+ - type: textarea
12
+ id: what-happened
13
+ attributes:
14
+ label: Describe the bug
15
+ description: A clear and concise description of what the bug is.
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ attributes:
20
+ label: Reproduction Steps
21
+ description: >
22
+ What you did to make it happen. Include any request payloads, API calls, or specific commands used.
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ attributes:
27
+ label: Expected behavior
28
+ description: >
29
+ A clear and concise description of what you expected to happen.
30
+ validations:
31
+ required: false
32
+ - type: textarea
33
+ attributes:
34
+ label: Screenshots and relevant files
35
+ description: >
36
+ If applicable, add screenshots or relevant files to help explain your problem.
37
+ validations:
38
+ required: false
39
+ - type: dropdown
40
+ id: platform
41
+ attributes:
42
+ label: "Platform"
43
+ description: "Select the platform where you encountered this bug"
44
+ options:
45
+ - "Google Cloud Platform"
46
+ - "Digital Ocean"
47
+ - "Local"
48
+ - "Other"
49
+ validations:
50
+ required: true
51
+ - type: dropdown
52
+ id: assign
53
+ attributes:
54
+ label: "Would you like to work on this issue?"
55
+ options:
56
+ - "Yes"
57
+ - type: checkboxes
58
+ attributes:
59
+ label: Checklist
60
+ description: >
61
+ Let's make sure you've properly done due diligence when reporting this issue!
62
+ options:
63
+ - label: I have searched the open issues for duplicates.
64
+ required: true
65
+ - label: I have shown the entire traceback, if possible.
66
+ required: true
67
+ - type: textarea
68
+ attributes:
69
+ label: Additional Context
70
+ description: Add any other context about the problem here.
.github/ISSUE_TEMPLATE/config.yml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ contact_links:
2
+ - name: Help or Questions?
3
+ url: https://www.skool.com/no-code-architects/about?ref=2f302c52a77541efa2dd5e8b27f3f8c9
4
+ about: Get courses, community, support daily calls and more.
5
+
6
+ blank_issues_enabled: true
7
+ # Allow blank issues for now?
.github/workflows/update-build-number.yml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Update Build Number
2
+ on:
3
+ push:
4
+ branches:
5
+ - build
6
+ permissions:
7
+ contents: write
8
+ jobs:
9
+ update-build-number:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+ token: ${{ secrets.ACTION_BYPASS }}
17
+
18
+ - name: Update build number
19
+ run: |
20
+ if [ ! -f build_number.txt ]; then
21
+ echo "0" > build_number.txt
22
+ fi
23
+ build_number=$(( $(cat build_number.txt) + 1 ))
24
+ echo $build_number > build_number.txt
25
+
26
+ # Update the version in your code file (e.g., version.py)
27
+ echo "BUILD_NUMBER = $build_number" > version.py
28
+
29
+ git config user.name github-actions
30
+ git config user.email github-actions@github.com
31
+ git add build_number.txt version.py
32
+ git commit -m "Build $build_number: Bump build number [skip ci]"
33
+ git push origin build
34
+
35
+ - name: Push changes to testing branch
36
+ run: |
37
+ git push origin build:testing --force
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ .env_variables.json
2
+ .DS_Store
3
+ .env_shell.json
4
+ .env
CONTRIBUTING.md ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to No-Code Architects Toolkit
2
+
3
+ Thanks for your interest in contributing! ❤️
4
+
5
+ This project exists to help **non-technical creators build smarter systems** — so every contribution should align with these core principles:
6
+
7
+ ✅ Simple
8
+ ✅ Useful
9
+ ✅ Low-maintenance
10
+
11
+ This repository is focused on new contributions and feature development. Please ensure all pull requests contain complete, debugged code that is ready for review. We do not accept submissions that require significant cleanup, completion work, or debugging by maintainers.
12
+
13
+ > If you like the project but don't know how to code, you can still support us in other ways:
14
+ >
15
+ > * ⭐ Star the project
16
+ > * 📣 Share it on social media
17
+ > * 🌲 Refer it to a friend or your community
18
+ > * 💸 [Sponsor the project](#)
19
+
20
+ If you need help or have questions, check out the GitHub [discussions](https://github.com/stephengpope/no-code-architects-toolkit/discussions) or join the [community](https://www.skool.com/no-code-architects/about?ref=2f302c52a77541efa2dd5e8b27f3f8c9).
21
+
22
+ ---
23
+
24
+ ## Table of Contents
25
+
26
+ * [What We Accept](#what-we-accept-)
27
+ * [What We Reject](#what-we-reject-)
28
+ * [Feature Evaluation Framework](#feature-evaluation-framework)
29
+ * [Technical Guidelines](#technical-guidelines)
30
+ * [Contribution Types](#contribution-types)
31
+ * [Branch Naming Conventions](#branch-naming-conventions)
32
+ * [Final Thoughts](#final-thoughts-%EF%B8%8F)
33
+
34
+ ---
35
+
36
+ ## What We Accept ✅
37
+
38
+ * Solves **common no-code challenges**
39
+ * **Reduces cost** or replaces paid APIs/tools
40
+ * Requires minimal input (has defaults)
41
+ * Is understandable by **non-technical users**
42
+ * Works out-of-the-box, no setup required
43
+ * One-time integrations — **no constant maintenance needed**
44
+ * Uses **existing input/output naming conventions**
45
+ * Follows our directory and structure conventions
46
+
47
+ ---
48
+
49
+ ## What We Reject ❌
50
+
51
+ * Features built for one person or edge-case
52
+ * Inconsistent input/output field names
53
+ * Requires polling, retries, or callback logic
54
+ * Needs babysitting or breaks frequently
55
+ * Lacks error handling or code comments
56
+ * Includes unused code, requirements, or bloat
57
+ * Adds huge packages that inflate Docker image size
58
+ * Leaves us with more work to do
59
+
60
+ ---
61
+
62
+ ## Feature Evaluation Framework
63
+
64
+ | Category | Ask This... | ✅ Accept if... | ❌ Reject if... |
65
+ | --------------------- | ---------------------------------------------- | ---------------------------------------------- | ------------------------------------------ |
66
+ | **Mission Fit** | Does this reduce cost or unify tools? | Replaces APIs, reduces costs or complexity | Adds noise or solves narrow edge cases |
67
+ | **Input Familiarity** | Are inputs familiar (`file_url`, `text`, etc)? | Uses standard names/types already in use | Introduces new terms for same ideas |
68
+ | **Input Clarity** | Would a non-tech user know what to enter? | Inputs like "Enter URL", "Choose format" | Needs tech explanation or experimentation |
69
+ | **Output Usefulness** | Can this plug straight into Make/Zapier? | Returns clean files, text, URLs | Returns raw data or deep nested structures |
70
+ | **Reliability** | Will it just work? | API is stable, no retries, consistent behavior | Depends on flaky APIs or fragile setup |
71
+ | **Maintenance Cost** | Will we have to maintain this? | One-and-done, doesn't change often | Vendor changes often, breaks silently |
72
+ | **Value vs. Effort** | Is it worth it? | High impact, frequently requested | Niche, low ROI |
73
+
74
+ ---
75
+
76
+ ## Technical Guidelines
77
+
78
+ > These guidelines help maintain a clean and production-ready project.
79
+
80
+ ### 🧠 Code Style
81
+
82
+ * Use **clear, descriptive names** (e.g., `convertImageToText`, not `imgTxt`)
83
+ * Comment your logic if it's not obvious
84
+ * Handle errors — don't let code crash silently
85
+ * Follow consistent formatting
86
+
87
+
88
+ ### 🧼 Clean Contributions
89
+
90
+ * Don't change files unrelated to your feature
91
+ * Don't leave behind unused requirements or code
92
+ * Don't introduce huge dependencies (we check image size)
93
+ * Use `git status` to review your working tree before you commit
94
+ ---
95
+
96
+ ## Branch Naming Conventions
97
+
98
+ All contributions should follow this process:
99
+
100
+ 1. Fork the [main repository](https://github.com/stephengpope/no-code-architects-toolkit)
101
+ 2. Clone your fork:
102
+ ```bash
103
+ git clone https://github.com/YOUR_USERNAME/no-code-architects-toolkit.git
104
+ cd no-code-architects-toolkit
105
+ ```
106
+ 3. Add the upstream repository:
107
+ ```bash
108
+ git remote add upstream https://github.com/stephengpope/no-code-architects-toolkit.git
109
+ ```
110
+ 4. Fetch and checkout the upstream build branch:
111
+ ```bash
112
+ git fetch upstream
113
+ git checkout -b your-feature-branch upstream/build
114
+ ```
115
+ 5. Name your feature branch following these patterns:
116
+ * For bug fixes: `fix/descriptive-bug-name`
117
+ * For new features: `feature/descriptive-feature-name`
118
+ * For documentation: `docs/descriptive-change`
119
+
120
+ Example:
121
+ ```bash
122
+ # For a new feature
123
+ git fetch upstream
124
+ git checkout -b feature/pdf-to-text-converter upstream/build
125
+
126
+ # For a bug fix
127
+ git fetch upstream
128
+ git checkout -b fix/webp-upload-crash upstream/build
129
+ ```
130
+
131
+ 6. After making your changes, push to your fork and create a pull request:
132
+ ```bash
133
+ git push origin your-feature-branch
134
+ ```
135
+ Then visit your fork on GitHub and create a pull request targeting the `build` branch of the main repository.
136
+
137
+ ---
138
+
139
+ ## Contribution Types
140
+
141
+ | Type | Good Example |
142
+ | ----------- | ---------------------------------------------------------------------- |
143
+ | 🐞 Bug Fix | "Fixes crash when uploading WebP files" |
144
+ | ⚡ Feature | "Adds endpoint to replace an expensive api" |
145
+ | 📚 Docs | "Improves deployment documentation (e.g., how to host on Netlify, AWS, Vercel, etc.)" |
146
+
147
+
148
+ ---
149
+
150
+ ## Final Thoughts 🧘‍♂️
151
+
152
+ * If it's not ready, don't submit it.
153
+ * Contributions should be helpful, obvious, and low-maintenance.
154
+ * The goal: **make complex tasks simple for no-code users**.
155
+
156
+ We're excited to see your contributions! 🎉
157
+
158
+ Let's build something useful, together.
Dockerfile ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Base image
2
+ FROM python:3.11-slim
3
+
4
+ # Install system dependencies, build tools, and libraries
5
+ RUN apt-get update && apt-get install -y --no-install-recommends \
6
+ ca-certificates \
7
+ wget \
8
+ tar \
9
+ xz-utils \
10
+ fonts-liberation \
11
+ fontconfig \
12
+ build-essential \
13
+ yasm \
14
+ cmake \
15
+ meson \
16
+ ninja-build \
17
+ nasm \
18
+ libssl-dev \
19
+ libvpx-dev \
20
+ libx264-dev \
21
+ libx265-dev \
22
+ libnuma-dev \
23
+ libmp3lame-dev \
24
+ libopus-dev \
25
+ libvorbis-dev \
26
+ libtheora-dev \
27
+ libspeex-dev \
28
+ libfreetype6-dev \
29
+ libfontconfig1-dev \
30
+ libgnutls28-dev \
31
+ libaom-dev \
32
+ libdav1d-dev \
33
+ librav1e-dev \
34
+ libzimg-dev \
35
+ libwebp-dev \
36
+ git \
37
+ pkg-config \
38
+ autoconf \
39
+ automake \
40
+ libtool \
41
+ libfribidi-dev \
42
+ libharfbuzz-dev \
43
+ libnss3 \
44
+ libatk1.0-0 \
45
+ libatk-bridge2.0-0 \
46
+ libcups2 \
47
+ libxcomposite1 \
48
+ libxrandr2 \
49
+ libxdamage1 \
50
+ libgbm1 \
51
+ libasound2 \
52
+ libpangocairo-1.0-0 \
53
+ libpangoft2-1.0-0 \
54
+ libgtk-3-0 \
55
+ && rm -rf /var/lib/apt/lists/*
56
+
57
+ # Install SRT from source (latest version using cmake)
58
+ RUN git clone https://github.com/Haivision/srt.git && \
59
+ cd srt && \
60
+ mkdir build && cd build && \
61
+ cmake .. && \
62
+ make -j$(nproc) && \
63
+ make install && \
64
+ cd ../.. && rm -rf srt
65
+
66
+ # Install SVT-AV1 from source
67
+ RUN git clone https://gitlab.com/AOMediaCodec/SVT-AV1.git && \
68
+ cd SVT-AV1 && \
69
+ git checkout v0.9.0 && \
70
+ cd Build && \
71
+ cmake .. && \
72
+ make -j$(nproc) && \
73
+ make install && \
74
+ cd ../.. && rm -rf SVT-AV1
75
+
76
+ # Install libvmaf from source
77
+ RUN git clone https://github.com/Netflix/vmaf.git && \
78
+ cd vmaf/libvmaf && \
79
+ meson build --buildtype release && \
80
+ ninja -C build && \
81
+ ninja -C build install && \
82
+ cd ../.. && rm -rf vmaf && \
83
+ ldconfig # Update the dynamic linker cache
84
+
85
+ # Manually build and install fdk-aac (since it is not available via apt-get)
86
+ RUN git clone https://github.com/mstorsjo/fdk-aac && \
87
+ cd fdk-aac && \
88
+ autoreconf -fiv && \
89
+ ./configure && \
90
+ make -j$(nproc) && \
91
+ make install && \
92
+ cd .. && rm -rf fdk-aac
93
+
94
+ # Install libunibreak (required for ASS_FEATURE_WRAP_UNICODE)
95
+ RUN git clone https://github.com/adah1972/libunibreak.git && \
96
+ cd libunibreak && \
97
+ ./autogen.sh && \
98
+ ./configure && \
99
+ make -j$(nproc) && \
100
+ make install && \
101
+ ldconfig && \
102
+ cd .. && rm -rf libunibreak
103
+
104
+ # Build and install libass with libunibreak support and ASS_FEATURE_WRAP_UNICODE enabled
105
+ RUN git clone https://github.com/libass/libass.git && \
106
+ cd libass && \
107
+ autoreconf -i && \
108
+ ./configure --enable-libunibreak || { cat config.log; exit 1; } && \
109
+ mkdir -p /app && echo "Config log located at: /app/config.log" && cp config.log /app/config.log && \
110
+ make -j$(nproc) || { echo "Libass build failed"; exit 1; } && \
111
+ make install && \
112
+ ldconfig && \
113
+ cd .. && rm -rf libass
114
+
115
+ # Build and install FFmpeg with all required features
116
+ RUN git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg && \
117
+ cd ffmpeg && \
118
+ git checkout n8.0 && \
119
+ PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/local/lib/pkgconfig" \
120
+ CFLAGS="-I/usr/include/freetype2" \
121
+ LDFLAGS="-L/usr/lib/x86_64-linux-gnu" \
122
+ ./configure --prefix=/usr/local \
123
+ --enable-gpl \
124
+ --enable-pthreads \
125
+ --enable-neon \
126
+ --enable-libaom \
127
+ --enable-libdav1d \
128
+ --enable-librav1e \
129
+ --enable-libsvtav1 \
130
+ --enable-libvmaf \
131
+ --enable-libzimg \
132
+ --enable-libx264 \
133
+ --enable-libx265 \
134
+ --enable-libvpx \
135
+ --enable-libwebp \
136
+ --enable-libmp3lame \
137
+ --enable-libopus \
138
+ --enable-libvorbis \
139
+ --enable-libtheora \
140
+ --enable-libspeex \
141
+ --enable-libass \
142
+ --enable-libfreetype \
143
+ --enable-libharfbuzz \
144
+ --enable-fontconfig \
145
+ --enable-libsrt \
146
+ --enable-filter=drawtext \
147
+ --extra-cflags="-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include" \
148
+ --extra-ldflags="-L/usr/lib/x86_64-linux-gnu -lfreetype -lfontconfig" \
149
+ --enable-gnutls \
150
+ && make -j$(nproc) && \
151
+ make install && \
152
+ cd .. && rm -rf ffmpeg
153
+
154
+ # Add /usr/local/bin to PATH (if not already included)
155
+ ENV PATH="/usr/local/bin:${PATH}"
156
+
157
+ # Copy fonts into the custom fonts directory
158
+ # COPY ./fonts /usr/share/fonts/custom
159
+
160
+ # Rebuild the font cache so that fontconfig can see the custom fonts
161
+ # RUN fc-cache -f -v
162
+
163
+ # Set work directory
164
+ WORKDIR /app
165
+
166
+ # Set environment variable for Whisper cache
167
+ ENV WHISPER_CACHE_DIR="/app/whisper_cache"
168
+
169
+ # Create cache directory (no need for chown here yet)
170
+ RUN mkdir -p ${WHISPER_CACHE_DIR}
171
+
172
+ # Copy the requirements file first to optimize caching
173
+ COPY requirements.txt .
174
+
175
+ # Install Python dependencies, upgrade pip
176
+ RUN pip install --no-cache-dir --upgrade pip && \
177
+ pip install --no-cache-dir -r requirements.txt && \
178
+ pip install playwright && \
179
+ pip install jsonschema
180
+
181
+ # Create the appuser
182
+ RUN useradd -m appuser
183
+
184
+ # Give appuser ownership of the /app directory (including whisper_cache)
185
+ RUN chown appuser:appuser /app
186
+
187
+ # Important: Switch to the appuser before downloading the model
188
+ USER appuser
189
+
190
+ RUN python -c "import os; print(os.environ.get('WHISPER_CACHE_DIR')); import whisper; whisper.load_model('base')"
191
+
192
+ # Install Playwright Chromium browser as appuser
193
+ RUN playwright install chromium
194
+
195
+ # Copy the rest of the application code
196
+ COPY . .
197
+
198
+
199
+ # Expose the port the app runs on
200
+ EXPOSE 8080
201
+
202
+ # Set environment variables
203
+ ENV PYTHONUNBUFFERED=1
204
+
205
+ RUN echo '#!/bin/bash\n\
206
+ gunicorn --bind 0.0.0.0:8080 \
207
+ --workers ${GUNICORN_WORKERS:-2} \
208
+ --timeout ${GUNICORN_TIMEOUT:-300} \
209
+ --worker-class sync \
210
+ --keep-alive 80 \
211
+ app:app' > /app/run_gunicorn.sh && \
212
+ chmod +x /app/run_gunicorn.sh
213
+
214
+ # Run the shell script
215
+ CMD ["/app/run_gunicorn.sh"]
LICENSE ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2025 Stephen G. Pope
2
+
3
+ GNU GENERAL PUBLIC LICENSE
4
+ Version 2, June 1991
5
+
6
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
7
+ <https://fsf.org/>
8
+ Everyone is permitted to copy and distribute verbatim copies
9
+ of this license document, but changing it is not allowed.
10
+
11
+ Preamble
12
+
13
+ The licenses for most software are designed to take away your
14
+ freedom to share and change it. By contrast, the GNU General Public
15
+ License is intended to guarantee your freedom to share and change free
16
+ software--to make sure the software is free for all its users. This
17
+ General Public License applies to most of the Free Software
18
+ Foundation's software and to any other program whose authors commit to
19
+ using it. (Some other Free Software Foundation software is covered by
20
+ the GNU Lesser General Public License instead.) You can apply it to
21
+ your programs, too.
22
+
23
+ When we speak of free software, we are referring to freedom, not
24
+ price. Our General Public Licenses are designed to make sure that you
25
+ have the freedom to distribute copies of free software (and charge for
26
+ this service if you wish), that you receive source code or can get it
27
+ if you want it, that you can change the software or use pieces of it
28
+ in new free programs; and that you know you can do these things.
29
+
30
+ To protect your rights, we need to make restrictions that forbid
31
+ anyone to deny you these rights or to ask you to surrender the rights.
32
+ These restrictions translate to certain responsibilities for you if you
33
+ distribute copies of the software, or if you modify it.
34
+
35
+ For example, if you distribute copies of such a program, whether
36
+ gratis or for a fee, you must give the recipients all the rights that
37
+ you have. You must make sure that they, too, receive or can get the
38
+ source code. And you must show them these terms so they know their
39
+ rights.
40
+
41
+ We protect your rights with two steps: (1) copyright the software, and
42
+ (2) offer you this license which gives you legal permission to copy,
43
+ distribute and/or modify the software.
44
+
45
+ Also, for each author's protection and ours, we want to make certain
46
+ that everyone understands that there is no warranty for this free
47
+ software. If the software is modified by someone else and passed on, we
48
+ want its recipients to know that what they have is not the original, so
49
+ that any problems introduced by others will not reflect on the original
50
+ authors' reputations.
51
+
52
+ Finally, any free program is threatened constantly by software
53
+ patents. We wish to avoid the danger that redistributors of a free
54
+ program will individually obtain patent licenses, in effect making the
55
+ program proprietary. To prevent this, we have made it clear that any
56
+ patent must be licensed for everyone's free use or not licensed at all.
57
+
58
+ The precise terms and conditions for copying, distribution and
59
+ modification follow.
60
+
61
+ GNU GENERAL PUBLIC LICENSE
62
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
63
+
64
+ 0. This License applies to any program or other work which contains
65
+ a notice placed by the copyright holder saying it may be distributed
66
+ under the terms of this General Public License. The "Program", below,
67
+ refers to any such program or work, and a "work based on the Program"
68
+ means either the Program or any derivative work under copyright law:
69
+ that is to say, a work containing the Program or a portion of it,
70
+ either verbatim or with modifications and/or translated into another
71
+ language. (Hereinafter, translation is included without limitation in
72
+ the term "modification".) Each licensee is addressed as "you".
73
+
74
+ Activities other than copying, distribution and modification are not
75
+ covered by this License; they are outside its scope. The act of
76
+ running the Program is not restricted, and the output from the Program
77
+ is covered only if its contents constitute a work based on the
78
+ Program (independent of having been made by running the Program).
79
+ Whether that is true depends on what the Program does.
80
+
81
+ 1. You may copy and distribute verbatim copies of the Program's
82
+ source code as you receive it, in any medium, provided that you
83
+ conspicuously and appropriately publish on each copy an appropriate
84
+ copyright notice and disclaimer of warranty; keep intact all the
85
+ notices that refer to this License and to the absence of any warranty;
86
+ and give any other recipients of the Program a copy of this License
87
+ along with the Program.
88
+
89
+ You may charge a fee for the physical act of transferring a copy, and
90
+ you may at your option offer warranty protection in exchange for a fee.
91
+
92
+ 2. You may modify your copy or copies of the Program or any portion
93
+ of it, thus forming a work based on the Program, and copy and
94
+ distribute such modifications or work under the terms of Section 1
95
+ above, provided that you also meet all of these conditions:
96
+
97
+ a) You must cause the modified files to carry prominent notices
98
+ stating that you changed the files and the date of any change.
99
+
100
+ b) You must cause any work that you distribute or publish, that in
101
+ whole or in part contains or is derived from the Program or any
102
+ part thereof, to be licensed as a whole at no charge to all third
103
+ parties under the terms of this License.
104
+
105
+ c) If the modified program normally reads commands interactively
106
+ when run, you must cause it, when started running for such
107
+ interactive use in the most ordinary way, to print or display an
108
+ announcement including an appropriate copyright notice and a
109
+ notice that there is no warranty (or else, saying that you provide
110
+ a warranty) and that users may redistribute the program under
111
+ these conditions, and telling the user how to view a copy of this
112
+ License. (Exception: if the Program itself is interactive but
113
+ does not normally print such an announcement, your work based on
114
+ the Program is not required to print an announcement.)
115
+
116
+ These requirements apply to the modified work as a whole. If
117
+ identifiable sections of that work are not derived from the Program,
118
+ and can be reasonably considered independent and separate works in
119
+ themselves, then this License, and its terms, do not apply to those
120
+ sections when you distribute them as separate works. But when you
121
+ distribute the same sections as part of a whole which is a work based
122
+ on the Program, the distribution of the whole must be on the terms of
123
+ this License, whose permissions for other licensees extend to the
124
+ entire whole, and thus to each and every part regardless of who wrote it.
125
+
126
+ Thus, it is not the intent of this section to claim rights or contest
127
+ your rights to work written entirely by you; rather, the intent is to
128
+ exercise the right to control the distribution of derivative or
129
+ collective works based on the Program.
130
+
131
+ In addition, mere aggregation of another work not based on the Program
132
+ with the Program (or with a work based on the Program) on a volume of
133
+ a storage or distribution medium does not bring the other work under
134
+ the scope of this License.
135
+
136
+ 3. You may copy and distribute the Program (or a work based on it,
137
+ under Section 2) in object code or executable form under the terms of
138
+ Sections 1 and 2 above provided that you also do one of the following:
139
+
140
+ a) Accompany it with the complete corresponding machine-readable
141
+ source code, which must be distributed under the terms of Sections
142
+ 1 and 2 above on a medium customarily used for software interchange; or,
143
+
144
+ b) Accompany it with a written offer, valid for at least three
145
+ years, to give any third party, for a charge no more than your
146
+ cost of physically performing source distribution, a complete
147
+ machine-readable copy of the corresponding source code, to be
148
+ distributed under the terms of Sections 1 and 2 above on a medium
149
+ customarily used for software interchange; or,
150
+
151
+ c) Accompany it with the information you received as to the offer
152
+ to distribute corresponding source code. (This alternative is
153
+ allowed only for noncommercial distribution and only if you
154
+ received the program in object code or executable form with such
155
+ an offer, in accord with Subsection b above.)
156
+
157
+ The source code for a work means the preferred form of the work for
158
+ making modifications to it. For an executable work, complete source
159
+ code means all the source code for all modules it contains, plus any
160
+ associated interface definition files, plus the scripts used to
161
+ control compilation and installation of the executable. However, as a
162
+ special exception, the source code distributed need not include
163
+ anything that is normally distributed (in either source or binary
164
+ form) with the major components (compiler, kernel, and so on) of the
165
+ operating system on which the executable runs, unless that component
166
+ itself accompanies the executable.
167
+
168
+ If distribution of executable or object code is made by offering
169
+ access to copy from a designated place, then offering equivalent
170
+ access to copy the source code from the same place counts as
171
+ distribution of the source code, even though third parties are not
172
+ compelled to copy the source along with the object code.
173
+
174
+ 4. You may not copy, modify, sublicense, or distribute the Program
175
+ except as expressly provided under this License. Any attempt
176
+ otherwise to copy, modify, sublicense or distribute the Program is
177
+ void, and will automatically terminate your rights under this License.
178
+ However, parties who have received copies, or rights, from you under
179
+ this License will not have their licenses terminated so long as such
180
+ parties remain in full compliance.
181
+
182
+ 5. You are not required to accept this License, since you have not
183
+ signed it. However, nothing else grants you permission to modify or
184
+ distribute the Program or its derivative works. These actions are
185
+ prohibited by law if you do not accept this License. Therefore, by
186
+ modifying or distributing the Program (or any work based on the
187
+ Program), you indicate your acceptance of this License to do so, and
188
+ all its terms and conditions for copying, distributing or modifying
189
+ the Program or works based on it.
190
+
191
+ 6. Each time you redistribute the Program (or any work based on the
192
+ Program), the recipient automatically receives a license from the
193
+ original licensor to copy, distribute or modify the Program subject to
194
+ these terms and conditions. You may not impose any further
195
+ restrictions on the recipients' exercise of the rights granted herein.
196
+ You are not responsible for enforcing compliance by third parties to
197
+ this License.
198
+
199
+ 7. If, as a consequence of a court judgment or allegation of patent
200
+ infringement or for any other reason (not limited to patent issues),
201
+ conditions are imposed on you (whether by court order, agreement or
202
+ otherwise) that contradict the conditions of this License, they do not
203
+ excuse you from the conditions of this License. If you cannot
204
+ distribute so as to satisfy simultaneously your obligations under this
205
+ License and any other pertinent obligations, then as a consequence you
206
+ may not distribute the Program at all. For example, if a patent
207
+ license would not permit royalty-free redistribution of the Program by
208
+ all those who receive copies directly or indirectly through you, then
209
+ the only way you could satisfy both it and this License would be to
210
+ refrain entirely from distribution of the Program.
211
+
212
+ If any portion of this section is held invalid or unenforceable under
213
+ any particular circumstance, the balance of the section is intended to
214
+ apply and the section as a whole is intended to apply in other
215
+ circumstances.
216
+
217
+ It is not the purpose of this section to induce you to infringe any
218
+ patents or other property right claims or to contest validity of any
219
+ such claims; this section has the sole purpose of protecting the
220
+ integrity of the free software distribution system, which is
221
+ implemented by public license practices. Many people have made
222
+ generous contributions to the wide range of software distributed
223
+ through that system in reliance on consistent application of that
224
+ system; it is up to the author/donor to decide if he or she is willing
225
+ to distribute software through any other system and a licensee cannot
226
+ impose that choice.
227
+
228
+ This section is intended to make thoroughly clear what is believed to
229
+ be a consequence of the rest of this License.
230
+
231
+ 8. If the distribution and/or use of the Program is restricted in
232
+ certain countries either by patents or by copyrighted interfaces, the
233
+ original copyright holder who places the Program under this License
234
+ may add an explicit geographical distribution limitation excluding
235
+ those countries, so that distribution is permitted only in or among
236
+ countries not thus excluded. In such case, this License incorporates
237
+ the limitation as if written in the body of this License.
238
+
239
+ 9. The Free Software Foundation may publish revised and/or new versions
240
+ of the General Public License from time to time. Such new versions will
241
+ be similar in spirit to the present version, but may differ in detail to
242
+ address new problems or concerns.
243
+
244
+ Each version is given a distinguishing version number. If the Program
245
+ specifies a version number of this License which applies to it and "any
246
+ later version", you have the option of following the terms and conditions
247
+ either of that version or of any later version published by the Free
248
+ Software Foundation. If the Program does not specify a version number of
249
+ this License, you may choose any version ever published by the Free Software
250
+ Foundation.
251
+
252
+ 10. If you wish to incorporate parts of the Program into other free
253
+ programs whose distribution conditions are different, write to the author
254
+ to ask for permission. For software which is copyrighted by the Free
255
+ Software Foundation, write to the Free Software Foundation; we sometimes
256
+ make exceptions for this. Our decision will be guided by the two goals
257
+ of preserving the free status of all derivatives of our free software and
258
+ of promoting the sharing and reuse of software generally.
259
+
260
+ NO WARRANTY
261
+
262
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
263
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
264
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
265
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
266
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
267
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
268
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
269
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
270
+ REPAIR OR CORRECTION.
271
+
272
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
273
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
274
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
275
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
276
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
277
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
278
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
279
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
280
+ POSSIBILITY OF SUCH DAMAGES.
281
+
282
+ END OF TERMS AND CONDITIONS
283
+
284
+ How to Apply These Terms to Your New Programs
285
+
286
+ If you develop a new program, and you want it to be of the greatest
287
+ possible use to the public, the best way to achieve this is to make it
288
+ free software which everyone can redistribute and change under these terms.
289
+
290
+ To do so, attach the following notices to the program. It is safest
291
+ to attach them to the start of each source file to most effectively
292
+ convey the exclusion of warranty; and each file should have at least
293
+ the "copyright" line and a pointer to where the full notice is found.
294
+
295
+ <one line to give the program's name and a brief idea of what it does.>
296
+ Copyright (C) <year> <name of author>
297
+
298
+ This program is free software; you can redistribute it and/or modify
299
+ it under the terms of the GNU General Public License as published by
300
+ the Free Software Foundation; either version 2 of the License, or
301
+ (at your option) any later version.
302
+
303
+ This program is distributed in the hope that it will be useful,
304
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
305
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
306
+ GNU General Public License for more details.
307
+
308
+ You should have received a copy of the GNU General Public License along
309
+ with this program; if not, see <https://www.gnu.org/licenses/>.
310
+
311
+ Also add information on how to contact you by electronic and paper mail.
312
+
313
+ If the program is interactive, make it output a short notice like this
314
+ when it starts in an interactive mode:
315
+
316
+ Gnomovision version 69, Copyright (C) year name of author
317
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
+ This is free software, and you are welcome to redistribute it
319
+ under certain conditions; type `show c' for details.
320
+
321
+ The hypothetical commands `show w' and `show c' should show the appropriate
322
+ parts of the General Public License. Of course, the commands you use may
323
+ be called something other than `show w' and `show c'; they could even be
324
+ mouse-clicks or menu items--whatever suits your program.
325
+
326
+ You should also get your employer (if you work as a programmer) or your
327
+ school, if any, to sign a "copyright disclaimer" for the program, if
328
+ necessary. Here is a sample; alter the names:
329
+
330
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
+
333
+ <signature of Moe Ghoul>, 1 April 1989
334
+ Moe Ghoul, President of Vice
335
+
336
+ This General Public License does not permit incorporating your program into
337
+ proprietary programs. If your program is a subroutine library, you may
338
+ consider it more useful to permit linking proprietary applications with the
339
+ library. If this is what you want to do, use the GNU Lesser General
340
+ Public License instead of this License.
README.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: toolkit
3
+ emoji: 🐨
4
+ colorFrom: gray
5
+ colorTo: purple
6
+ sdk: docker
7
+ pinned: false
8
+ app_port: 8080
9
+ ---
app.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2025 Stephen G. Pope
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
17
+
18
+
19
+ from flask import Flask, request
20
+ from queue import Queue
21
+ from services.webhook import send_webhook
22
+ import threading
23
+ import uuid
24
+ import os
25
+ import time
26
+ from version import BUILD_NUMBER # Import the BUILD_NUMBER
27
+ from app_utils import log_job_status, discover_and_register_blueprints # Import the discover_and_register_blueprints function
28
+
29
+ MAX_QUEUE_LENGTH = int(os.environ.get('MAX_QUEUE_LENGTH', 0))
30
+
31
+ def create_app():
32
+ app = Flask(__name__)
33
+
34
+ # Create a queue to hold tasks
35
+ task_queue = Queue()
36
+ queue_id = id(task_queue) # Generate a single queue_id for this worker
37
+
38
+ # Function to process tasks from the queue
39
+ def process_queue():
40
+ while True:
41
+ job_id, data, task_func, queue_start_time = task_queue.get()
42
+ queue_time = time.time() - queue_start_time
43
+ run_start_time = time.time()
44
+ pid = os.getpid() # Get the PID of the actual processing thread
45
+
46
+ # Log job status as running
47
+ log_job_status(job_id, {
48
+ "job_status": "running",
49
+ "job_id": job_id,
50
+ "queue_id": queue_id,
51
+ "process_id": pid,
52
+ "response": None
53
+ })
54
+
55
+ response = task_func()
56
+ run_time = time.time() - run_start_time
57
+ total_time = time.time() - queue_start_time
58
+
59
+ response_data = {
60
+ "endpoint": response[1],
61
+ "code": response[2],
62
+ "id": data.get("id"),
63
+ "job_id": job_id,
64
+ "response": response[0] if response[2] == 200 else None,
65
+ "message": "success" if response[2] == 200 else response[0],
66
+ "pid": pid,
67
+ "queue_id": queue_id,
68
+ "run_time": round(run_time, 3),
69
+ "queue_time": round(queue_time, 3),
70
+ "total_time": round(total_time, 3),
71
+ "queue_length": task_queue.qsize(),
72
+ "build_number": BUILD_NUMBER # Add build number to response
73
+ }
74
+
75
+ # Log job status as done
76
+ log_job_status(job_id, {
77
+ "job_status": "done",
78
+ "job_id": job_id,
79
+ "queue_id": queue_id,
80
+ "process_id": pid,
81
+ "response": response_data
82
+ })
83
+
84
+ # Only send webhook if webhook_url has an actual value (not an empty string)
85
+ if data.get("webhook_url") and data.get("webhook_url") != "":
86
+ send_webhook(data.get("webhook_url"), response_data)
87
+
88
+ task_queue.task_done()
89
+
90
+ # Start the queue processing in a separate thread
91
+ threading.Thread(target=process_queue, daemon=True).start()
92
+
93
+ # Decorator to add tasks to the queue or bypass it
94
+ def queue_task(bypass_queue=False):
95
+ def decorator(f):
96
+ def wrapper(*args, **kwargs):
97
+ job_id = str(uuid.uuid4())
98
+ data = request.json if request.is_json else {}
99
+ pid = os.getpid() # Get PID for non-queued tasks
100
+ start_time = time.time()
101
+
102
+ if bypass_queue or 'webhook_url' not in data:
103
+
104
+ # Log job status as running immediately (bypassing queue)
105
+ log_job_status(job_id, {
106
+ "job_status": "running",
107
+ "job_id": job_id,
108
+ "queue_id": queue_id,
109
+ "process_id": pid,
110
+ "response": None
111
+ })
112
+
113
+ response = f(job_id=job_id, data=data, *args, **kwargs)
114
+ run_time = time.time() - start_time
115
+
116
+ response_obj = {
117
+ "code": response[2],
118
+ "id": data.get("id"),
119
+ "job_id": job_id,
120
+ "response": response[0] if response[2] == 200 else None,
121
+ "message": "success" if response[2] == 200 else response[0],
122
+ "run_time": round(run_time, 3),
123
+ "queue_time": 0,
124
+ "total_time": round(run_time, 3),
125
+ "pid": pid,
126
+ "queue_id": queue_id,
127
+ "queue_length": task_queue.qsize(),
128
+ "build_number": BUILD_NUMBER # Add build number to response
129
+ }
130
+
131
+ # Log job status as done
132
+ log_job_status(job_id, {
133
+ "job_status": "done",
134
+ "job_id": job_id,
135
+ "queue_id": queue_id,
136
+ "process_id": pid,
137
+ "response": response_obj
138
+ })
139
+
140
+ return response_obj, response[2]
141
+ else:
142
+ if MAX_QUEUE_LENGTH > 0 and task_queue.qsize() >= MAX_QUEUE_LENGTH:
143
+ error_response = {
144
+ "code": 429,
145
+ "id": data.get("id"),
146
+ "job_id": job_id,
147
+ "message": f"MAX_QUEUE_LENGTH ({MAX_QUEUE_LENGTH}) reached",
148
+ "pid": pid,
149
+ "queue_id": queue_id,
150
+ "queue_length": task_queue.qsize(),
151
+ "build_number": BUILD_NUMBER # Add build number to response
152
+ }
153
+
154
+ # Log the queue overflow error
155
+ log_job_status(job_id, {
156
+ "job_status": "done",
157
+ "job_id": job_id,
158
+ "queue_id": queue_id,
159
+ "process_id": pid,
160
+ "response": error_response
161
+ })
162
+
163
+ return error_response, 429
164
+
165
+ # Log job status as queued
166
+ log_job_status(job_id, {
167
+ "job_status": "queued",
168
+ "job_id": job_id,
169
+ "queue_id": queue_id,
170
+ "process_id": pid,
171
+ "response": None
172
+ })
173
+
174
+ task_queue.put((job_id, data, lambda: f(job_id=job_id, data=data, *args, **kwargs), start_time))
175
+
176
+ return {
177
+ "code": 202,
178
+ "id": data.get("id"),
179
+ "job_id": job_id,
180
+ "message": "processing",
181
+ "pid": pid,
182
+ "queue_id": queue_id,
183
+ "max_queue_length": MAX_QUEUE_LENGTH if MAX_QUEUE_LENGTH > 0 else "unlimited",
184
+ "queue_length": task_queue.qsize(),
185
+ "build_number": BUILD_NUMBER # Add build number to response
186
+ }, 202
187
+ return wrapper
188
+ return decorator
189
+
190
+ app.queue_task = queue_task
191
+
192
+ # Register special route for Next.js root asset paths first
193
+ from routes.v1.media.feedback import create_root_next_routes
194
+ create_root_next_routes(app)
195
+
196
+ # Use the discover_and_register_blueprints function to register all blueprints
197
+ discover_and_register_blueprints(app)
198
+
199
+ return app
200
+
201
+ app = create_app()
202
+
203
+ if __name__ == '__main__':
204
+ app.run(host='0.0.0.0', port=8080)
app_utils.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2025 Stephen G. Pope
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
17
+
18
+
19
+ from flask import request, jsonify, current_app
20
+ from functools import wraps
21
+ import jsonschema
22
+ import os
23
+ import json
24
+ import time
25
+ from config import LOCAL_STORAGE_PATH
26
+
27
+ def validate_payload(schema):
28
+ def decorator(f):
29
+ @wraps(f)
30
+ def decorated_function(*args, **kwargs):
31
+ if not request.json:
32
+ return jsonify({"message": "Missing JSON in request"}), 400
33
+ try:
34
+ jsonschema.validate(instance=request.json, schema=schema)
35
+ except jsonschema.exceptions.ValidationError as validation_error:
36
+ return jsonify({"message": f"Invalid payload: {validation_error.message}"}), 400
37
+
38
+ return f(*args, **kwargs)
39
+ return decorated_function
40
+ return decorator
41
+
42
+ def log_job_status(job_id, data):
43
+ """
44
+ Log job status to a file in the STORAGE_PATH/jobs folder
45
+
46
+ Args:
47
+ job_id (str): The unique job ID
48
+ data (dict): Data to write to the log file
49
+ """
50
+ jobs_dir = os.path.join(LOCAL_STORAGE_PATH, 'jobs')
51
+
52
+ # Create jobs directory if it doesn't exist
53
+ if not os.path.exists(jobs_dir):
54
+ os.makedirs(jobs_dir, exist_ok=True)
55
+
56
+ # Create or update the job log file
57
+ job_file = os.path.join(jobs_dir, f"{job_id}.json")
58
+
59
+ # Write data directly to file
60
+ with open(job_file, 'w') as f:
61
+ json.dump(data, f, indent=2)
62
+
63
+ def queue_task_wrapper(bypass_queue=False):
64
+ def decorator(f):
65
+ def wrapper(*args, **kwargs):
66
+ return current_app.queue_task(bypass_queue=bypass_queue)(f)(*args, **kwargs)
67
+ return wrapper
68
+ return decorator
69
+
70
+ def discover_and_register_blueprints(app, base_dir='routes'):
71
+ """
72
+ Dynamically discovers and registers all Flask blueprints in the routes directory.
73
+ Recursively searches all subdirectories for Python modules containing Blueprint instances.
74
+
75
+ Args:
76
+ app (Flask): The Flask application instance
77
+ base_dir (str): Base directory to start searching for blueprints (default: 'routes')
78
+ """
79
+ import importlib
80
+ import pkgutil
81
+ import inspect
82
+ import sys
83
+ import os
84
+ from flask import Blueprint
85
+ import logging
86
+ import glob
87
+
88
+ logger = logging.getLogger(__name__)
89
+ logger.info(f"Discovering blueprints in {base_dir}")
90
+
91
+ # Add the current working directory to sys.path if it's not already there
92
+ cwd = os.getcwd()
93
+ if cwd not in sys.path:
94
+ sys.path.insert(0, cwd)
95
+
96
+ # Get the absolute path to the base directory
97
+ if not os.path.isabs(base_dir):
98
+ base_dir = os.path.join(cwd, base_dir)
99
+
100
+ registered_blueprints = set()
101
+
102
+ # Find all Python files in the routes directory, including subdirectories
103
+ python_files = glob.glob(os.path.join(base_dir, '**', '*.py'), recursive=True)
104
+ logger.info(f"Found {len(python_files)} Python files in {base_dir}")
105
+
106
+ for file_path in python_files:
107
+ try:
108
+ # Convert file path to import path
109
+ rel_path = os.path.relpath(file_path, cwd)
110
+ # Remove .py extension
111
+ module_path = os.path.splitext(rel_path)[0]
112
+ # Convert path separators to dots for import
113
+ module_path = module_path.replace(os.path.sep, '.')
114
+
115
+ # Skip __init__.py files
116
+ if module_path.endswith('__init__'):
117
+ continue
118
+
119
+ #logger.info(f"Attempting to import module: {module_path}")
120
+
121
+ # Import the module
122
+ module = importlib.import_module(module_path)
123
+
124
+ # Find all Blueprint instances in the module
125
+ for name, obj in inspect.getmembers(module):
126
+ if isinstance(obj, Blueprint) and obj not in registered_blueprints:
127
+ pid = os.getpid()
128
+ logger.info(f"PID {pid} Registering: {module_path}")
129
+ app.register_blueprint(obj)
130
+ registered_blueprints.add(obj)
131
+
132
+ except Exception as e:
133
+ logger.error(f"Error importing module {module_path}: {str(e)}")
134
+
135
+ logger.info(f"PID {pid} Registered {len(registered_blueprints)} blueprints")
136
+ return registered_blueprints
build_number.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ 200
config.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2025 Stephen G. Pope
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
17
+
18
+
19
+ import os
20
+ import logging
21
+
22
+ # Retrieve the API key from environment variables
23
+ API_KEY = os.environ.get('API_KEY')
24
+ if not API_KEY:
25
+ raise ValueError("API_KEY environment variable is not set")
26
+
27
+ # Storage path setting
28
+ LOCAL_STORAGE_PATH = os.environ.get('LOCAL_STORAGE_PATH', '/tmp')
29
+
30
+ # GCP environment variables
31
+ GCP_SA_CREDENTIALS = os.environ.get('GCP_SA_CREDENTIALS', '')
32
+ GCP_BUCKET_NAME = os.environ.get('GCP_BUCKET_NAME', '')
33
+
34
+ def validate_env_vars(provider):
35
+
36
+ """ Validate the necessary environment variables for the selected storage provider """
37
+ required_vars = {
38
+ 'GCP': ['GCP_BUCKET_NAME', 'GCP_SA_CREDENTIALS'],
39
+ 'S3': ['S3_ENDPOINT_URL', 'S3_ACCESS_KEY', 'S3_SECRET_KEY', 'S3_BUCKET_NAME', 'S3_REGION'],
40
+ 'S3_DO': ['S3_ENDPOINT_URL', 'S3_ACCESS_KEY', 'S3_SECRET_KEY']
41
+ }
42
+
43
+ missing_vars = [var for var in required_vars[provider] if not os.getenv(var)]
44
+ if missing_vars:
45
+ raise ValueError(f"Missing environment variables for {provider} storage: {', '.join(missing_vars)}")
docker-compose.local.minio.n8n.md ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Local Development with MinIO and n8n
2
+
3
+ This setup provides a complete local development environment for the No Code Architect Toolkit with integrated MinIO S3-compatible storage and n8n workflow automation.
4
+
5
+ ## What's Included
6
+
7
+ - **NCA Toolkit**: Built locally from source (no pre-built image required)
8
+ - **MinIO**: S3-compatible object storage with web console for local file management
9
+ - **n8n**: Workflow automation platform for connecting and orchestrating services
10
+ - **Custom Network**: All services communicate through a dedicated Docker network
11
+ - **Persistent Storage**: Data persists between container restarts
12
+
13
+ ## Prerequisites
14
+
15
+ - Docker and Docker Compose installed
16
+ - Git (to clone the repository)
17
+ - At least 2GB available RAM
18
+ - At least 5GB available disk space
19
+
20
+ ---
21
+
22
+ ## Quick Start
23
+
24
+ ### 1. Prepare Environment Configuration
25
+
26
+ Copy the example environment file and customize it:
27
+
28
+ ```bash
29
+ cp .env.local.minio.n8n.example .env.local.minio.n8n
30
+ ```
31
+
32
+ Edit `.env.local.minio.n8n` with your preferred settings. The defaults work for most local development scenarios.
33
+
34
+ ### 2. Start the Development Environment
35
+
36
+ ```bash
37
+ docker compose -f docker-compose.local.minio.n8n.yml up -d
38
+ ```
39
+
40
+ ### 3. Access the Applications
41
+
42
+ Once all services are running, you can access:
43
+
44
+ - **NCA Toolkit API**: http://localhost:8080
45
+ - **n8n Workflow Interface**: http://localhost:5678
46
+ - **MinIO Console**: http://localhost:9001
47
+ - Username: `minioadmin`
48
+ - Password: `minioadmin123`
49
+
50
+ ### 4. Verify Setup
51
+
52
+ Test the NCA Toolkit API:
53
+
54
+ ```bash
55
+ curl -H "x-api-key: local-dev-key-123" http://localhost:8080/v1/toolkit/test
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Environment Configuration
61
+
62
+ The `.env.local.minio.n8n` file contains all necessary configuration:
63
+
64
+ ### Application Settings
65
+ ```env
66
+ APP_NAME=NCAToolkit
67
+ APP_DEBUG=true
68
+ APP_DOMAIN=localhost:8080
69
+ APP_URL=http://localhost:8080
70
+ API_KEY=local-dev-key-123
71
+ ```
72
+
73
+ ### MinIO S3 Storage Settings
74
+ ```env
75
+ S3_ENDPOINT_URL=http://minio:9000
76
+ S3_ACCESS_KEY=minioadmin
77
+ S3_SECRET_KEY=minioadmin123
78
+ S3_REGION=us-east-1
79
+ S3_BUCKET_NAME=nca-toolkit-local
80
+ ```
81
+
82
+ ### n8n Configuration
83
+ ```env
84
+ N8N_HOST=localhost
85
+ N8N_PORT=5678
86
+ N8N_PROTOCOL=http
87
+ WEBHOOK_URL=http://localhost:5678/
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Service Details
93
+
94
+ ### NCA Toolkit (Port 8080)
95
+ - Built from local Dockerfile
96
+ - Connects to MinIO for file storage
97
+ - API accessible at http://localhost:8080
98
+ - Uses local development API key: `local-dev-key-123`
99
+
100
+ ### MinIO (Ports 9000, 9001)
101
+ - **API Endpoint**: http://localhost:9000 (S3-compatible API)
102
+ - **Web Console**: http://localhost:9001
103
+ - **Bucket**: `nca-toolkit-local` (auto-created and configured as public)
104
+ - **Credentials**: minioadmin / minioadmin123
105
+
106
+ ### n8n (Port 5678)
107
+ - **Web Interface**: http://localhost:5678
108
+ - **Webhook URL**: http://localhost:5678/
109
+ - **File Sharing**: `./local-files` directory mounted for easy file access
110
+ - Can connect to both NCA Toolkit and MinIO services
111
+
112
+ ---
113
+
114
+ ## Development Workflow
115
+
116
+ ### Making Code Changes
117
+
118
+ 1. **Edit source code** in your local directory
119
+ 2. **Rebuild the NCA Toolkit container**:
120
+ ```bash
121
+ docker compose -f docker-compose.local.minio.n8n.yml build ncat
122
+ docker compose -f docker-compose.local.minio.n8n.yml up -d
123
+ ```
124
+
125
+ ### Viewing Logs
126
+
127
+ ```bash
128
+ # All services
129
+ docker compose -f docker-compose.local.minio.n8n.yml logs -f
130
+
131
+ # Specific service
132
+ docker compose -f docker-compose.local.minio.n8n.yml logs -f ncat
133
+ docker compose -f docker-compose.local.minio.n8n.yml logs -f minio
134
+ docker compose -f docker-compose.local.minio.n8n.yml logs -f n8n
135
+ ```
136
+
137
+ ### Managing Storage
138
+
139
+ #### Access MinIO Console
140
+ 1. Open http://localhost:9001
141
+ 2. Login with `minioadmin` / `minioadmin123`
142
+ 3. Browse the `nca-toolkit-local` bucket
143
+ 4. Upload/download files as needed
144
+
145
+ #### Reset MinIO Data
146
+ ```bash
147
+ docker compose -f docker-compose.local.minio.n8n.yml down
148
+ docker volume rm no-code-architects-toolkit_minio_data
149
+ docker compose -f docker-compose.local.minio.n8n.yml up -d
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Service Communication
155
+
156
+ All services communicate through the `nca-network` Docker network:
157
+
158
+ - **n8n → NCA Toolkit**: `http://ncat:8080`
159
+ - **n8n → MinIO**: `http://minio:9000` (S3 API)
160
+ - **NCA Toolkit → MinIO**: `http://minio:9000` (internal network)
161
+
162
+ ### n8n Integration with NCA Toolkit
163
+
164
+ #### Quick Test Setup
165
+
166
+ 1. **Access n8n**: Open http://localhost:5678
167
+ 2. **Create a new workflow**
168
+ 3. **Add an HTTP Request node** with these settings:
169
+ - **Method**: GET
170
+ - **URL**: `http://ncat:8080/v1/toolkit/test`
171
+ - **Headers**:
172
+ - Key: `x-api-key`
173
+ - Value: `local-dev-key-123`
174
+
175
+ #### Example: Testing the Toolkit Connection
176
+
177
+ **HTTP Request Node Configuration:**
178
+ ```json
179
+ {
180
+ "method": "GET",
181
+ "url": "http://ncat:8080/v1/toolkit/test",
182
+ "headers": {
183
+ "x-api-key": "local-dev-key-123"
184
+ }
185
+ }
186
+ ```
187
+
188
+ **Expected Response:**
189
+ ```json
190
+ {
191
+ "message": "NCA Toolkit is working correctly",
192
+ "status": "success"
193
+ }
194
+ ```
195
+
196
+ #### Example: Media Processing Workflow
197
+
198
+ **HTTP Request Node for Media Transcription:**
199
+ ```json
200
+ {
201
+ "method": "POST",
202
+ "url": "http://ncat:8080/v1/media/transcribe",
203
+ "headers": {
204
+ "x-api-key": "local-dev-key-123",
205
+ "Content-Type": "application/json"
206
+ },
207
+ "body": {
208
+ "media_url": "https://example.com/audio.mp3",
209
+ "language": "en",
210
+ "response_format": "json"
211
+ }
212
+ }
213
+ ```
214
+
215
+ #### All Available NCA Toolkit Endpoints
216
+
217
+ Use the base URL `http://ncat:8080` with any of the API endpoints documented in the main README:
218
+
219
+ - `http://ncat:8080/v1/toolkit/test` - Test connection
220
+ - `http://ncat:8080/v1/media/transcribe` - Transcribe audio/video
221
+ - `http://ncat:8080/v1/video/caption` - Add captions to videos
222
+ - `http://ncat:8080/v1/image/screenshot/webpage` - Screenshot web pages
223
+ - And all other endpoints listed in the main documentation
224
+
225
+ #### Tips for n8n Integration
226
+
227
+ 1. **Always use the internal network URL**: `http://ncat:8080` (not `http://localhost:8080`)
228
+ 2. **Include the API key header**: `x-api-key: local-dev-key-123`
229
+ 3. **For file uploads**: Use the MinIO integration or webhook URLs for large files
230
+ 4. **Error handling**: Add error handling nodes to manage API timeouts or failures
231
+
232
+ ---
233
+
234
+ ## Data Persistence
235
+
236
+ The following data persists between container restarts:
237
+
238
+ - **Application Storage**: `storage` volume (`/app/storage`)
239
+ - **Application Logs**: `logs` volume (`/app/logs`)
240
+ - **MinIO Data**: `minio_data` volume
241
+ - **n8n Workflows**: `n8n_data` volume (`/home/node/.n8n`)
242
+ - **Shared Files**: `./local-files` directory
243
+
244
+ ---
245
+
246
+ ## Troubleshooting
247
+
248
+ ### Services Won't Start
249
+ ```bash
250
+ # Check service status
251
+ docker compose -f docker-compose.local.minio.n8n.yml ps
252
+
253
+ # View error logs
254
+ docker compose -f docker-compose.local.minio.n8n.yml logs
255
+ ```
256
+
257
+ ### Port Conflicts
258
+ If ports 8080, 5678, 9000, or 9001 are already in use, modify the port mappings in `docker-compose.local.minio.n8n.yml`:
259
+
260
+ ```yaml
261
+ ports:
262
+ - "8081:8080" # Change 8080 to 8081
263
+ ```
264
+
265
+ ### MinIO Bucket Issues
266
+ The `minio-init` service automatically creates and configures the bucket. If issues occur:
267
+
268
+ ```bash
269
+ # Restart the init service
270
+ docker compose -f docker-compose.local.minio.n8n.yml restart minio-init
271
+
272
+ # Check init logs
273
+ docker compose -f docker-compose.local.minio.n8n.yml logs minio-init
274
+ ```
275
+
276
+ ### API Authentication Errors
277
+ Ensure you're using the correct API key from `.env.local.minio.n8n`:
278
+ - Default: `local-dev-key-123`
279
+ - Header: `x-api-key: local-dev-key-123`
280
+
281
+ ---
282
+
283
+ ## Stopping the Environment
284
+
285
+ ```bash
286
+ # Stop all services
287
+ docker compose -f docker-compose.local.minio.n8n.yml down
288
+
289
+ # Stop and remove volumes (deletes all data)
290
+ docker compose -f docker-compose.local.minio.n8n.yml down -v
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Architecture Overview
296
+
297
+ ```
298
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
299
+ │ NCA Toolkit │ │ n8n │ │ MinIO │
300
+ │ localhost:8080│◄──►│ localhost:5678│◄──►│ localhost:9000 │
301
+ │ │ │ │ │ (S3 API) │
302
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
303
+ │ │ │
304
+ └───────────────────────┼───────────────────────┘
305
+
306
+ ┌─────────────────┐
307
+ │ MinIO Console │
308
+ │ localhost:9001 │
309
+ └─────────────────┘
310
+
311
+ ┌─────────────────┐
312
+ │ nca-network │
313
+ │ (Docker Bridge) │
314
+ └─────────────────┘
315
+ ```
316
+
317
+ This setup provides a complete local development environment with file storage, workflow automation, and the NCA Toolkit API all working together seamlessly.
docker-compose.local.minio.n8n.yml ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ ncat:
3
+ build: .
4
+ env_file:
5
+ - .env.local.minio.n8n
6
+ ports:
7
+ - "8080:8080"
8
+ volumes:
9
+ - storage:/app/storage
10
+ - logs:/app/logs
11
+ restart: unless-stopped
12
+ depends_on:
13
+ - minio
14
+ - minio-init
15
+ networks:
16
+ - nca-network
17
+
18
+ minio:
19
+ image: minio/minio:latest
20
+ command: server /data --console-address ":9001"
21
+ ports:
22
+ - "9000:9000"
23
+ - "9001:9001"
24
+ environment:
25
+ MINIO_ROOT_USER: minioadmin
26
+ MINIO_ROOT_PASSWORD: minioadmin123
27
+ volumes:
28
+ - minio_data:/data
29
+ restart: unless-stopped
30
+ networks:
31
+ - nca-network
32
+
33
+ minio-init:
34
+ image: minio/mc:latest
35
+ depends_on:
36
+ - minio
37
+ entrypoint: >
38
+ /bin/sh -c "
39
+ sleep 5;
40
+ /usr/bin/mc alias set myminio http://minio:9000 minioadmin minioadmin123;
41
+ /usr/bin/mc mb myminio/nca-toolkit-local --ignore-existing;
42
+ /usr/bin/mc anonymous set public myminio/nca-toolkit-local;
43
+ echo 'MinIO bucket nca-toolkit-local created and configured as public';
44
+ "
45
+ networks:
46
+ - nca-network
47
+
48
+ n8n:
49
+ image: docker.n8n.io/n8nio/n8n
50
+ restart: unless-stopped
51
+ ports:
52
+ - "5678:5678"
53
+ environment:
54
+ - N8N_HOST=localhost
55
+ - N8N_PORT=5678
56
+ - N8N_PROTOCOL=http
57
+ - NODE_ENV=production
58
+ - WEBHOOK_URL=http://localhost:5678/
59
+ - GENERIC_TIMEZONE=UTC
60
+ - N8N_SECURE_COOKIE=false
61
+ volumes:
62
+ - n8n_data:/home/node/.n8n
63
+ - ./local-files:/files
64
+ networks:
65
+ - nca-network
66
+
67
+ volumes:
68
+ storage:
69
+ driver: local
70
+ logs:
71
+ driver: local
72
+ minio_data:
73
+ driver: local
74
+ n8n_data:
75
+ driver: local
76
+
77
+ networks:
78
+ nca-network:
79
+ driver: bridge
docker-compose.md ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Install No Code Architect Toolkit with Docker
2
+
3
+ Installation of No Code Architect Toolkit with Docker offers the following advantages:
4
+ - Install No Code Architect Toolkit in a clean environment.
5
+ - Simplify the setup process.
6
+ - Avoid compatibility issues across different operating systems with Docker's consistent environment.
7
+
8
+ > **Info**
9
+ > If your domain/subdomain is already pointed to the server, start at step 2.
10
+ > If you have already installed Docker and Docker-Compose, start at step 3.
11
+
12
+ ---
13
+
14
+ ## 1. DNS Setup
15
+
16
+ Point your domain/subdomain to the server. Add an A record to route the domain/subdomain accordingly:
17
+
18
+ - **Type**: A
19
+ - **Name**: The desired domain/subdomain
20
+ - **IP Address**: `<IP_OF_YOUR_SERVER>`
21
+
22
+ ---
23
+
24
+ ## 2. Install Docker
25
+
26
+ This can vary depending on the Linux distribution used. Below are instructions for Ubuntu:
27
+
28
+ ### Set up Docker's APT Repository
29
+
30
+ ```bash
31
+ # Add Docker's official GPG key:
32
+ sudo apt-get update
33
+ sudo apt-get install ca-certificates curl
34
+ sudo install -m 0755 -d /etc/apt/keyrings
35
+ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
36
+ sudo chmod a+r /etc/apt/keyrings/docker.asc
37
+
38
+ # Add the repository to APT sources:
39
+ echo \
40
+ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
41
+ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
42
+ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
43
+ sudo apt-get update
44
+ ```
45
+
46
+ ### Install the Docker Packages
47
+
48
+ ```bash
49
+ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
50
+ ```
51
+
52
+ ---
53
+
54
+ ## 3. Create Docker Compose File
55
+
56
+ Create a `docker-compose.yml` file and paste the following configuration:
57
+
58
+ ### With SSL Support
59
+ Enables SSL/TLS for secure, encrypted communications. Ideal for those wanting a hands-off approach to SSL setup.
60
+
61
+ ```yaml
62
+ services:
63
+ traefik:
64
+ image: "traefik"
65
+ restart: unless-stopped
66
+ command:
67
+ - "--api=true"
68
+ - "--api.insecure=true"
69
+ - "--providers.docker=true"
70
+ - "--providers.docker.exposedbydefault=false"
71
+ - "--entrypoints.web.address=:80"
72
+ - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
73
+ - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
74
+ - "--entrypoints.websecure.address=:443"
75
+ - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
76
+ - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
77
+ - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
78
+ ports:
79
+ - "80:80"
80
+ - "443:443"
81
+ volumes:
82
+ - traefik_data:/letsencrypt
83
+ - /var/run/docker.sock:/var/run/docker.sock:ro
84
+ ncat:
85
+ image: stephengpope/no-code-architects-toolkit:latest
86
+ env_file:
87
+ - .env
88
+ labels:
89
+ - traefik.enable=true
90
+ - traefik.http.routers.ncat.rule=Host(`${APP_DOMAIN}`)
91
+ - traefik.http.routers.ncat.tls=true
92
+ - traefik.http.routers.ncat.entrypoints=web,websecure
93
+ - traefik.http.routers.ncat.tls.certresolver=mytlschallenge
94
+ volumes:
95
+ - storage:/var/www/html/storage/app
96
+ - logs:/var/www/html/storage/logs
97
+ restart: unless-stopped
98
+
99
+ volumes:
100
+ traefik_data:
101
+ driver: local
102
+ storage:
103
+ driver: local
104
+ logs:
105
+ driver: local
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 4. Create `.env` File
111
+
112
+ Create an `.env` file and configure it accordingly:
113
+
114
+ ```env
115
+ # The name of your application.
116
+ APP_NAME=NCAToolkit
117
+
118
+ # Debug mode setting. Set to `false` for production environments.
119
+ APP_DEBUG=false
120
+
121
+ # Your app's domain or subdomain, without the 'http://' or 'https://' prefix.
122
+ APP_DOMAIN=example.com
123
+
124
+ # Full application URL is automatically configured; no modification required.
125
+ APP_URL=https://${APP_DOMAIN}
126
+
127
+ # SSL settings
128
+ SSL_EMAIL=user@example.com
129
+
130
+ # API_KEY
131
+ # Purpose: Used for API authentication.
132
+ # Requirement: Mandatory.
133
+ API_KEY=your_api_key_here
134
+
135
+ # s3 Compatible Storage Env Vars
136
+ #
137
+ #S3_ACCESS_KEY=your_access_key
138
+ #S3_SECRET_KEY=your_secret_key
139
+ #S3_ENDPOINT_URL=https://your-endpoint-url
140
+ #S3_REGION=your-region
141
+ #S3_BUCKET_NAME=your-bucket-name
142
+
143
+
144
+ # Google Cloud Storage Env Variables
145
+ #
146
+ # GCP_SA_CREDENTIALS
147
+ # Purpose: The JSON credentials for the GCP Service Account.
148
+ # Requirement: Mandatory if using GCP storage.
149
+ #GCP_SA_CREDENTIALS=/path/to/your/gcp/service_account.json
150
+
151
+ # GCP_BUCKET_NAME
152
+ # Purpose: The name of the GCP storage bucket.
153
+ # Requirement: Mandatory if using GCP storage.
154
+ #GCP_BUCKET_NAME=your_gcp_bucket_name
155
+
156
+ # STORAGE_PATH
157
+ # Purpose: The base path for storage operations.
158
+ # Default: GCP
159
+ # Requirement: Optional.
160
+ #STORAGE_PATH=GCP
161
+
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 5. Start Docker Compose
167
+
168
+ Start No Code Architect Toolkit using the following command:
169
+
170
+ ```bash
171
+ docker compose up -d
172
+ ```
173
+
174
+ To view logs in real time:
175
+
176
+ ```bash
177
+ docker compose logs -f
178
+ ```
179
+
180
+ To stop the containers:
181
+
182
+ ```bash
183
+ docker compose stop
184
+ ```
185
+
186
+ To restart and reload env vars
187
+
188
+ # First update your .env file with the correct values
189
+ # Then run:
190
+
191
+ ```bash
192
+ docker compose up -d --force-recreate ncat
193
+ ```
194
+
195
+ ---
196
+
197
+ ## 6. Done
198
+
199
+ No Code Architect Toolkit is now accessible through the specified APP_URL. For example:
200
+ [https://example.com](https://example.com)
docker-compose.yml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ traefik:
3
+ image: "traefik"
4
+ restart: unless-stopped
5
+ command:
6
+ - "--api=true"
7
+ - "--api.insecure=true"
8
+ - "--providers.docker=true"
9
+ - "--providers.docker.exposedbydefault=false"
10
+ - "--entrypoints.web.address=:80"
11
+ - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
12
+ - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
13
+ - "--entrypoints.websecure.address=:443"
14
+ - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
15
+ - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
16
+ - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
17
+ ports:
18
+ - "80:80"
19
+ - "443:443"
20
+ volumes:
21
+ - traefik_data:/letsencrypt
22
+ - /var/run/docker.sock:/var/run/docker.sock:ro
23
+ ncat:
24
+ image: stephengpope/no-code-architects-toolkit:latest
25
+ env_file:
26
+ - .env
27
+ labels:
28
+ - traefik.enable=true
29
+ - traefik.http.routers.ncat.rule=Host(`${APP_DOMAIN}`)
30
+ - traefik.http.routers.ncat.tls=true
31
+ - traefik.http.routers.ncat.entrypoints=web,websecure
32
+ - traefik.http.routers.ncat.tls.certresolver=mytlschallenge
33
+ volumes:
34
+ - storage:/var/www/html/storage/app
35
+ - logs:/var/www/html/storage/logs
36
+ restart: unless-stopped
37
+
38
+ volumes:
39
+ traefik_data:
40
+ driver: local
41
+ storage:
42
+ driver: local
43
+ logs:
44
+ driver: local
docs/adding_routes.md ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Adding New Routes
2
+
3
+ This document explains how to add new routes to the application using the dynamic route registration system.
4
+
5
+ ## Overview
6
+
7
+ The application now uses a dynamic route registration system that automatically discovers and registers all Flask blueprints in the `routes` directory. This means you no longer need to manually import and register blueprints in `app.py`.
8
+
9
+ ## How to Add a New Route
10
+
11
+ 1. **Create a new route file**
12
+
13
+ Create a new Python file in the appropriate location in the `routes` directory. For a v1 API endpoint, you would typically place it in a subdirectory under `routes/v1/` based on the functionality.
14
+
15
+ For example:
16
+ ```
17
+ routes/v1/email/send_email.py
18
+ ```
19
+
20
+ 2. **Define your Blueprint**
21
+
22
+ In your route file, define a Flask Blueprint with a unique name. Make sure to follow the naming convention:
23
+
24
+ ```python
25
+ # routes/v1/email/send_email.py
26
+ from flask import Blueprint, request
27
+ from services.authentication import authenticate
28
+ from app_utils import queue_task_wrapper
29
+
30
+ v1_email_send_bp = Blueprint('v1_email_send', __name__)
31
+
32
+ @v1_email_send_bp.route('/v1/email/send', methods=['POST'])
33
+ @authenticate
34
+ @queue_task_wrapper(bypass_queue=False)
35
+ def send_email(job_id, data):
36
+ """
37
+ Send an email
38
+
39
+ Args:
40
+ job_id (str): Job ID assigned by queue_task_wrapper
41
+ data (dict): Request data containing email details
42
+
43
+ Returns:
44
+ Tuple of (response_data, endpoint_string, status_code)
45
+ """
46
+ # Your implementation here
47
+ endpoint = "/v1/email/send"
48
+
49
+ # Return response
50
+ return {"message": "Email sent"}, endpoint, 200
51
+ ```
52
+
53
+ 3. **That's it!**
54
+
55
+ No need to modify `app.py`. The blueprint will be automatically discovered and registered when the application starts.
56
+
57
+ ## Naming Conventions
58
+
59
+ When creating new routes, please follow these naming conventions:
60
+
61
+ 1. **Blueprint names**: Use the format `{version}_{category}_{action}_bp`
62
+ - Example: `v1_email_send_bp` for sending emails
63
+
64
+ 2. **Route paths**: Use the format `/{version}/{category}/{action}`
65
+ - Example: `/v1/email/send`
66
+
67
+ 3. **File structure**: Place files in directories that match the route structure
68
+ - Example: `routes/v1/email/send_email.py`
69
+
70
+ ## Testing Your Route
71
+
72
+ After adding your route, restart the application and your new endpoint should be available immediately.
73
+
74
+ ## Troubleshooting
75
+
76
+ If your route isn't being registered:
77
+
78
+ 1. Check logs for any import errors
79
+ 2. Ensure your blueprint variable is defined at the module level
80
+ 3. Verify the blueprint name follows the naming convention
81
+ 4. Make sure your Python file is in the correct directory under `routes/`
docs/audio/concatenate.md ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Audio Concatenation API Endpoint Documentation
2
+
3
+ ## Overview
4
+
5
+ The `/v1/audio/concatenate` endpoint provides functionality to combine multiple audio files into a single audio file. This endpoint is part of the v1 API structure and is registered in the main application through the `v1_audio_concatenate_bp` Blueprint. It leverages the application's queuing system to handle asynchronous processing, which is particularly useful for potentially time-consuming audio processing operations.
6
+
7
+ ## Endpoint
8
+
9
+ - **URL**: `/v1/audio/concatenate`
10
+ - **Method**: `POST`
11
+
12
+ ## Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key`: Required. Your API authentication key.
17
+
18
+ ### Body Parameters
19
+
20
+ | Parameter | Type | Required | Description |
21
+ |-----------|------|----------|-------------|
22
+ | `audio_urls` | Array | Yes | An array of objects, each containing an `audio_url` property pointing to an audio file to be concatenated. Must contain at least one item. |
23
+ | `webhook_url` | String | No | A URL to receive a callback notification when processing is complete. If provided, the request will be processed asynchronously. |
24
+ | `id` | String | No | A custom identifier for tracking the request. |
25
+
26
+ Each object in the `audio_urls` array must have:
27
+ - `audio_url`: String (URI format). The URL of an audio file to be concatenated.
28
+
29
+ ### Example Request
30
+
31
+ ```json
32
+ {
33
+ "audio_urls": [
34
+ { "audio_url": "https://example.com/audio1.mp3" },
35
+ { "audio_url": "https://example.com/audio2.mp3" },
36
+ { "audio_url": "https://example.com/audio3.mp3" }
37
+ ],
38
+ "webhook_url": "https://your-webhook-endpoint.com/callback",
39
+ "id": "custom-request-id-123"
40
+ }
41
+ ```
42
+
43
+ ### Example cURL Command
44
+
45
+ ```bash
46
+ curl -X POST \
47
+ https://api.example.com/v1/audio/concatenate \
48
+ -H 'Content-Type: application/json' \
49
+ -H 'x-api-key: your-api-key-here' \
50
+ -d '{
51
+ "audio_urls": [
52
+ { "audio_url": "https://example.com/audio1.mp3" },
53
+ { "audio_url": "https://example.com/audio2.mp3" }
54
+ ],
55
+ "webhook_url": "https://your-webhook-endpoint.com/callback",
56
+ "id": "custom-request-id-123"
57
+ }'
58
+ ```
59
+
60
+ ## Response
61
+
62
+ ### Synchronous Response (No webhook_url provided)
63
+
64
+ If no `webhook_url` is provided, the request will be processed synchronously and return:
65
+
66
+ ```json
67
+ {
68
+ "code": 200,
69
+ "id": "custom-request-id-123",
70
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
71
+ "response": "https://storage.example.com/combined-audio-file.mp3",
72
+ "message": "success",
73
+ "run_time": 2.345,
74
+ "queue_time": 0,
75
+ "total_time": 2.345,
76
+ "pid": 12345,
77
+ "queue_id": 67890,
78
+ "queue_length": 0,
79
+ "build_number": "1.0.123"
80
+ }
81
+ ```
82
+
83
+ ### Asynchronous Response (webhook_url provided)
84
+
85
+ If a `webhook_url` is provided, the request will be queued for processing and immediately return:
86
+
87
+ ```json
88
+ {
89
+ "code": 202,
90
+ "id": "custom-request-id-123",
91
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
92
+ "message": "processing",
93
+ "pid": 12345,
94
+ "queue_id": 67890,
95
+ "max_queue_length": "unlimited",
96
+ "queue_length": 1,
97
+ "build_number": "1.0.123"
98
+ }
99
+ ```
100
+
101
+ When processing is complete, a webhook will be sent to the provided URL with the following payload:
102
+
103
+ ```json
104
+ {
105
+ "endpoint": "/v1/audio/concatenate",
106
+ "code": 200,
107
+ "id": "custom-request-id-123",
108
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
109
+ "response": "https://storage.example.com/combined-audio-file.mp3",
110
+ "message": "success",
111
+ "pid": 12345,
112
+ "queue_id": 67890,
113
+ "run_time": 3.456,
114
+ "queue_time": 1.234,
115
+ "total_time": 4.690,
116
+ "queue_length": 0,
117
+ "build_number": "1.0.123"
118
+ }
119
+ ```
120
+
121
+ ### Error Responses
122
+
123
+ #### Invalid Request Format (400 Bad Request)
124
+
125
+ ```json
126
+ {
127
+ "code": 400,
128
+ "id": null,
129
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
130
+ "message": "Invalid request: 'audio_urls' is a required property",
131
+ "pid": 12345,
132
+ "queue_id": 67890,
133
+ "queue_length": 0,
134
+ "build_number": "1.0.123"
135
+ }
136
+ ```
137
+
138
+ #### Authentication Error (401 Unauthorized)
139
+
140
+ ```json
141
+ {
142
+ "code": 401,
143
+ "message": "Invalid or missing API key",
144
+ "build_number": "1.0.123"
145
+ }
146
+ ```
147
+
148
+ #### Queue Limit Reached (429 Too Many Requests)
149
+
150
+ ```json
151
+ {
152
+ "code": 429,
153
+ "id": "custom-request-id-123",
154
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
155
+ "message": "MAX_QUEUE_LENGTH (100) reached",
156
+ "pid": 12345,
157
+ "queue_id": 67890,
158
+ "queue_length": 100,
159
+ "build_number": "1.0.123"
160
+ }
161
+ ```
162
+
163
+ #### Processing Error (500 Internal Server Error)
164
+
165
+ ```json
166
+ {
167
+ "code": 500,
168
+ "id": "custom-request-id-123",
169
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
170
+ "message": "Error downloading audio file: Connection refused",
171
+ "pid": 12345,
172
+ "queue_id": 67890,
173
+ "queue_length": 0,
174
+ "build_number": "1.0.123"
175
+ }
176
+ ```
177
+
178
+ ## Error Handling
179
+
180
+ - **Missing Required Parameters**: If `audio_urls` is missing or empty, a 400 Bad Request response will be returned.
181
+ - **Invalid URL Format**: If any `audio_url` is not a valid URI, a 400 Bad Request response will be returned.
182
+ - **Authentication Failure**: If the API key is invalid or missing, a 401 Unauthorized response will be returned.
183
+ - **Queue Limit**: If the queue is full (when MAX_QUEUE_LENGTH is set), a 429 Too Many Requests response will be returned.
184
+ - **Processing Errors**: Any errors during audio download, processing, or upload will result in a 500 Internal Server Error response with details in the message field.
185
+
186
+ ## Usage Notes
187
+
188
+ 1. **Asynchronous Processing**: For long audio files, it's recommended to use the `webhook_url` parameter to process the request asynchronously.
189
+ 2. **File Formats**: The service supports common audio formats. The output will be in a standard format (typically MP3).
190
+ 3. **File Size**: There may be limits on the size of audio files that can be processed. Very large files might cause timeouts or failures.
191
+ 4. **Queue Behavior**: If the system is under heavy load, requests with `webhook_url` will be queued. The MAX_QUEUE_LENGTH environment variable controls the maximum queue size.
192
+
193
+ ## Common Issues
194
+
195
+ 1. **Inaccessible Audio URLs**: Ensure all audio URLs are publicly accessible. Private or authentication-required URLs will cause failures.
196
+ 2. **Incompatible Audio Formats**: Some exotic audio formats might not be supported. Stick to common formats like MP3, WAV, or AAC.
197
+ 3. **Webhook Failures**: If your webhook endpoint is unavailable when the processing completes, you might not receive the completion notification.
198
+ 4. **Timeout Issues**: Very large audio files might cause timeouts during download or processing.
199
+
200
+ ## Best Practices
201
+
202
+ 1. **Use Webhooks for Large Files**: Always use the webhook approach for large audio files or when concatenating many files.
203
+ 2. **Include an ID**: Always include a custom `id` parameter to help track your requests, especially in webhook responses.
204
+ 3. **Error Handling**: Implement robust error handling in your client application to handle various HTTP status codes.
205
+ 4. **Webhook Reliability**: Ensure your webhook endpoint is reliable and can handle retries if necessary.
206
+ 5. **File Preparation**: Pre-process your audio files to ensure they have compatible formats, sample rates, and channel configurations for best results.
207
+ 6. **Queue Monitoring**: Monitor the `queue_length` in responses to understand system load and adjust your request patterns if needed.
docs/cloud-installation/do.md ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Installing on Digital Ocean
2
+
3
+ This guide walks you through deploying the No-Code Architects Toolkit API on Digital Ocean's App Platform.
4
+
5
+ ## Prerequisites
6
+
7
+ - A Digital Ocean account ([Sign up here](https://www.digitalocean.com/))
8
+ - Basic familiarity with Digital Ocean App Platform
9
+ - A credit/debit card for billing (you'll only be charged for what you use)
10
+
11
+ ## Step 1: Create a New Project
12
+
13
+ 1. Sign in to your Digital Ocean account
14
+ 2. Create a new project or select an existing one
15
+ 3. This will organize your resources for the NCA Toolkit
16
+
17
+ ## Step 2: Create a Digital Ocean Space
18
+
19
+ You'll need to create a Space (Digital Ocean's object storage) for the toolkit to store processed files:
20
+
21
+ 1. Navigate to **Spaces Object Storage** in the Digital Ocean dashboard
22
+ 2. Click **Create a Space**
23
+ 3. Select a region (e.g., New York)
24
+ 4. Give your bucket a name (e.g., `nca-toolkit-bucket`)
25
+ 5. Select your project
26
+ 6. Click **Create Space**
27
+
28
+ ## Step 3: Generate API Keys for Your Space
29
+
30
+ 1. From your new Space, go to **Settings**
31
+ 2. Click **Create Access Key**
32
+ 3. Select **Full Access**
33
+ 4. Give your key a name (e.g., `nca-toolkit-key`)
34
+ 5. Click **Create Access Key**
35
+ 6. **IMPORTANT**: Save both the Access Key and Secret Key shown - you will only see them once!
36
+ 7. Also copy the Space URL (endpoint) for use in the next step
37
+
38
+ ## Step 4: Deploy the App
39
+
40
+ 1. From your Digital Ocean dashboard, click **Create** and select **App**
41
+ 2. Choose **Container Image** as the deployment source
42
+ 3. Select **Docker Hub** for the repository
43
+ 4. Enter `stephengpope/no-code-architects-toolkit` as the image name
44
+ 5. Enter `latest` for the image tag
45
+ 6. Click **Next**
46
+ 7. If needed, edit the name to remove any extra dashes (Digital Ocean may show an error for long names)
47
+ 8. Choose **Web Service** as the service type
48
+
49
+ ## Step 5: Configure Resources
50
+
51
+ 1. Select a plan with adequate resources for your needs:
52
+ - For testing, a $50/month instance provides good performance
53
+ - For smaller workloads, you can select a smaller instance
54
+ - Note: You're only charged for the time the server is running
55
+ 2. Set Containers to 1
56
+ 3. Close the resource selection dialog
57
+
58
+ ## Step 6: Configure Environment Variables
59
+
60
+ Add the following environment variables exactly as shown (be careful with underscores vs. dashes and avoid any leading/trailing spaces):
61
+
62
+ 1. `API_KEY`: Your API key (e.g., `test123` for testing - change for production)
63
+ 2. `S3_ENDPOINT_URL`: The URL of your Space (copied from Step 3)
64
+ 3. `S3_ACCESS_KEY`: The access key from Step 3
65
+ 4. `S3_SECRET_KEY`: The secret key from Step 3
66
+ 5. `S3_BUCKET_NAME`: The name of your Space bucket (e.g., `nca-toolkit-bucket`)
67
+ 6. `S3_REGION`: The region code of your Space (e.g., `NYC3` for New York)
68
+
69
+ ## Step 7: Finalize and Deploy
70
+
71
+ 1. For Deployment Region, select a region close to your location (e.g., San Francisco)
72
+ 2. You can use the default app name or choose a custom name
73
+ 3. Click **Create Resource**
74
+ 4. Wait for the deployment to complete (this may take a few minutes)
75
+ - You may need to refresh the page to see updates
76
+
77
+ ## Step 8: Test Your Deployment
78
+
79
+ ### Using Postman
80
+
81
+ 1. Sign up for or log in to [Postman](https://www.postman.com/)
82
+ 2. Import the [NCA Toolkit Postman Collection](https://bit.ly/49Gkh61)
83
+ 3. Fork the collection to your workspace
84
+ 4. Create a new environment:
85
+ - Name it "Digital Ocean" or similar
86
+ - Add a variable `x-api-key` with the value matching your API_KEY (e.g., `test123`)
87
+ - Add a variable `base_url` with the value of your app's URL (shown in the Digital Ocean dashboard)
88
+ - Save the environment
89
+ 5. In the collection, navigate to the `toolkit/authenticate` endpoint and click Send
90
+ 6. If you receive a success response, your deployment is working correctly
91
+ 7. Then test the `toolkit/test` endpoint to verify complete functionality
92
+
93
+ ## Monitoring and Management
94
+
95
+ - **Overview**: View basic information about your app
96
+ - **Insights**: Monitor CPU and memory usage
97
+ - **Runtime Logs**: View logs of API calls and server activity
98
+ - **Console**: Access the server's command line (rarely needed)
99
+ - **Settings**: Modify your app's configuration
100
+
101
+ ## Next Steps
102
+
103
+ Now that you have successfully deployed the NCA Toolkit API, you can:
104
+ - Explore all the available endpoints in the Postman collection
105
+ - Integrate the API with your applications
106
+ - Consider securing your API key with a more complex value
107
+ - Scale your resources up or down based on your usage requirements
108
+
109
+ Remember, Digital Ocean charges based on usage, so you can always delete the app when you're not using it to save costs.
docs/cloud-installation/gcp.md ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Installing on the Google Cloud Platform (GCP)
2
+
3
+ ## 🎥 Video Instructions
4
+
5
+ Watch **[Detailed Video Instructions](https://youtu.be/6bC93sek9v8)** to set up the No-Code Architects Toolkit API.
6
+
7
+ - Use the **Docker Image** below:
8
+
9
+ ```
10
+ stephengpope/no-code-architects-toolkit:latest
11
+ ```
12
+
13
+ ### Video Resources
14
+
15
+ - **[Postman Template](https://bit.ly/49Gkh61)**
16
+ - **[NCA Toolkit API GPT](https://bit.ly/4feDDk4)**
17
+
18
+ Or use the guide below walks you through the steps to install the NCA Toolkit API on GCP.
19
+
20
+ ---
21
+
22
+ ## **Prerequisites**
23
+ - A Google Cloud account. [Sign up here](https://cloud.google.com/) if you don't already have one.
24
+ - New users receive $300 in free credits.
25
+ - Basic knowledge of GCP services such as Cloud Run and Cloud Storage.
26
+ - A terminal or code editor for managing files.
27
+
28
+ ---
29
+
30
+ ## **Step 1: Create a Google Cloud Project**
31
+ 1. Log into the [GCP Console](https://console.cloud.google.com/).
32
+ 2. Click on the **Project Selector** in the top navigation bar and select **New Project**.
33
+ 3. Enter a project name, such as `NCA Toolkit Project`.
34
+ 4. Click **Create**.
35
+
36
+ ---
37
+
38
+ ## **Step 2: Enable Required APIs**
39
+ Enable the following APIs:
40
+ - **Cloud Storage API**
41
+ - **Cloud Storage JSON API**
42
+ - **Cloud Run API**
43
+
44
+ ### **How to Enable APIs:**
45
+ 1. In the GCP Console, navigate to **APIs & Services** > **Enable APIs and Services**.
46
+ 2. Search for each API, click on it, and enable it.
47
+
48
+ ---
49
+
50
+ ## **Step 3: Create a Service Account**
51
+ 1. Navigate to **IAM & Admin** > **Service Accounts** in the GCP Console.
52
+ 2. Click **+ Create Service Account**.
53
+ - Enter a name (e.g., `NCA Toolkit Service Account`).
54
+ 3. Assign the following roles to the service account:
55
+ - **Storage Admin**
56
+ - **Viewer**
57
+ 4. Click **Done** to create the service account.
58
+ 5. Open the service account details and navigate to the **Keys** tab.
59
+ - Click **Add Key** > **Create New Key**.
60
+ - Choose **JSON** format, download the file, and store it securely.
61
+
62
+ ---
63
+
64
+ ## **Step 4: Create a Cloud Storage Bucket**
65
+ 1. Navigate to **Storage** > **Buckets** in the GCP Console.
66
+ 2. Click **+ Create Bucket**.
67
+ - Choose a unique bucket name (e.g., `nca-toolkit-bucket`).
68
+ - Leave default settings, but:
69
+ - Uncheck **Enforce public access prevention**.
70
+ - Set **Access Control** to **Uniform**.
71
+ 3. Click **Create** to finish.
72
+ 4. Go to the bucket permissions, and add **allUsers** as a principal with the role:
73
+ - **Storage Object Viewer**.
74
+ 5. Save changes.
75
+
76
+ ---
77
+
78
+ ## **Step 5: Deploy on Google Cloud Run**
79
+
80
+ ### 1. Navigate to Cloud Run
81
+ - Open the **Cloud Run** service in the **Google Cloud Console**.
82
+
83
+ ### 2. Create a New Service
84
+ - Click **Create Service**.
85
+ - Then **Deploy one revision from Docker Hub using the image below**:
86
+
87
+ ```
88
+ stephengpope/no-code-architects-toolkit:latest
89
+ ```
90
+
91
+ ### 3. Allow Unauthenticated Invocations
92
+ - Check the box to **allow unauthenticated invocations**.
93
+
94
+ ### 4. Configure Resource Allocation
95
+ - Set **Memory**: `16 GB`.
96
+ - Set **CPU**: `4 CPUs`.
97
+ - Set **CPU Allocation**: **Always Allocated**.
98
+
99
+ ### 5. Adjust Scaling Settings
100
+ - **Minimum Instances**: `0` (to minimize cost during idle times).
101
+ - **Maximum Instances**: `5` (adjustable based on expected load).
102
+
103
+ ### 6. Use Second-Generation Servers
104
+ - Scroll to **Platform Version** and select **Second Generation**.
105
+ - Second-generation servers offer better performance and feature support for advanced use cases.
106
+
107
+ ### 7. Add Environment Variables
108
+ - Add the following environment variables:
109
+ - `API_KEY`: Your API key (e.g., `Test123`).
110
+ - `GCP_BUCKET_NAME`: The name of your Cloud Storage bucket.
111
+ - `GCP_SA_CREDENTIALS`: The JSON key of your service account.
112
+ - Paste the **entire contents** of the downloaded JSON key file into this field.
113
+ - Ensure:
114
+ - Proper JSON formatting.
115
+ - No leading or trailing spaces.
116
+
117
+ ### 8. Configure Advanced Settings
118
+ - Set the **Container Port**: Default to `8080`.
119
+ - **Request Timeout**: `300 seconds` (to handle long-running requests).
120
+ - Enable **Startup Boost** to improve performance for the first request after a cold start.
121
+
122
+ ### 9. Deploy the Service
123
+ - Verify all settings and click **Create**.
124
+ - The deployment process might take a few minutes. Once completed, a green checkmark should appear in the Cloud Run dashboard.
125
+
126
+ By following these steps, the NCA Toolkit will be successfully deployed and accessible via Google Cloud Run with second-generation servers for optimal performance.
127
+
128
+ ---
129
+
130
+ ## **Step 6: Test the Deployment**
131
+
132
+ 1. Install **[Postman Template](https://bit.ly/49Gkh61)** on your computer.
133
+ 2. Import the API example requests from the NCA Toolkit GitHub repository.
134
+ 3. Configure two environment variables in Postman:
135
+ - `base_url`: Your deployed Cloud Run service URL.
136
+ - `x-api-key`: The API key you configured in **Step 5**.
137
+ 4. Use the example requests to validate that the API is functioning correctly.
138
+ 5. Use the **[NCA Toolkit API GPT](https://bit.ly/4feDDk4)** to learn more.
139
+
140
+ By following these steps, your NCA Toolkit API should be successfully deployed on Google Cloud Platform.
docs/code/execute/execute_python.md ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Execute Python Code Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/code/execute/python` endpoint allows users to execute Python code on the server. This endpoint is part of the version 1.0 API structure defined in `app.py`. It is designed to provide a secure and controlled environment for executing Python code, with features like input validation, output capturing, and timeout handling.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/code/execute/python`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+
22
+ - `code` (string, required): The Python code to be executed.
23
+ - `timeout` (integer, optional): The maximum execution time in seconds, between 1 and 300. Default is 30 seconds.
24
+ - `webhook_url` (string, optional): The URL to receive the execution result via a webhook.
25
+ - `id` (string, optional): A unique identifier for the request.
26
+
27
+ The `validate_payload` directive in the routes file enforces the following JSON schema for the request body:
28
+
29
+ ```json
30
+ {
31
+ "type": "object",
32
+ "properties": {
33
+ "code": {"type": "string"},
34
+ "timeout": {"type": "integer", "minimum": 1, "maximum": 300},
35
+ "webhook_url": {"type": "string", "format": "uri"},
36
+ "id": {"type": "string"}
37
+ },
38
+ "required": ["code"],
39
+ "additionalProperties": False
40
+ }
41
+ ```
42
+
43
+ ### Example Request
44
+
45
+ **Request Payload:**
46
+
47
+ ```json
48
+ {
49
+ "code": "print('Hello, World!')",
50
+ "timeout": 10,
51
+ "webhook_url": "https://example.com/webhook",
52
+ "id": "unique-request-id"
53
+ }
54
+ ```
55
+
56
+ **cURL Command:**
57
+
58
+ ```bash
59
+ curl -X POST \
60
+ -H "x-api-key: YOUR_API_KEY" \
61
+ -H "Content-Type: application/json" \
62
+ -d '{"code": "print('Hello, World!')", "timeout": 10, "webhook_url": "https://example.com/webhook", "id": "unique-request-id"}' \
63
+ http://your-api-endpoint/v1/code/execute/python
64
+ ```
65
+
66
+ ## 4. Response
67
+
68
+ ### Success Response
69
+
70
+ The success response follows the general response format defined in `app.py`. Here's an example:
71
+
72
+ ```json
73
+ {
74
+ "endpoint": "/v1/code/execute/python",
75
+ "code": 200,
76
+ "id": "unique-request-id",
77
+ "job_id": "generated-job-id",
78
+ "response": {
79
+ "result": null,
80
+ "stdout": "Hello, World!\n",
81
+ "stderr": "",
82
+ "exit_code": 0
83
+ },
84
+ "message": "success",
85
+ "pid": 12345,
86
+ "queue_id": 1234567890,
87
+ "run_time": 0.123,
88
+ "queue_time": 0.0,
89
+ "total_time": 0.123,
90
+ "queue_length": 0,
91
+ "build_number": "1.0.0"
92
+ }
93
+ ```
94
+
95
+ ### Error Responses
96
+
97
+ #### Missing or Invalid Parameters
98
+
99
+ **Status Code:** 400 Bad Request
100
+
101
+ ```json
102
+ {
103
+ "error": "Missing or invalid parameters",
104
+ "stdout": "",
105
+ "exit_code": 400
106
+ }
107
+ ```
108
+
109
+ #### Execution Error
110
+
111
+ **Status Code:** 400 Bad Request
112
+
113
+ ```json
114
+ {
115
+ "error": "Error message from the executed code",
116
+ "stdout": "Output from the executed code",
117
+ "exit_code": 400
118
+ }
119
+ ```
120
+
121
+ #### Execution Timeout
122
+
123
+ **Status Code:** 408 Request Timeout
124
+
125
+ ```json
126
+ {
127
+ "error": "Execution timed out after 10 seconds"
128
+ }
129
+ ```
130
+
131
+ #### Internal Server Error
132
+
133
+ **Status Code:** 500 Internal Server Error
134
+
135
+ ```json
136
+ {
137
+ "error": "An internal server error occurred",
138
+ "stdout": "",
139
+ "stderr": "",
140
+ "exit_code": 500
141
+ }
142
+ ```
143
+
144
+ ## 5. Error Handling
145
+
146
+ The endpoint handles various types of errors, including:
147
+
148
+ - Missing or invalid parameters (400 Bad Request)
149
+ - Execution errors, such as syntax errors or exceptions (400 Bad Request)
150
+ - Execution timeout (408 Request Timeout)
151
+ - Internal server errors (500 Internal Server Error)
152
+
153
+ The main application context (`app.py`) also includes error handling for queue overload (429 Too Many Requests) and other general errors.
154
+
155
+ ## 6. Usage Notes
156
+
157
+ - The executed code runs in a sandboxed environment, with limited access to system resources.
158
+ - The code execution is limited to a maximum of 300 seconds (5 minutes) by default, but this can be adjusted using the `timeout` parameter.
159
+ - The execution result, including stdout, stderr, and the return value, is captured and returned in the response.
160
+ - If a `webhook_url` is provided, the execution result will also be sent to the specified webhook.
161
+
162
+ ## 7. Common Issues
163
+
164
+ - Attempting to execute code that accesses restricted resources or performs disallowed operations may result in an execution error.
165
+ - Long-running or resource-intensive code may trigger the execution timeout.
166
+ - Providing an invalid `webhook_url` will prevent the execution result from being delivered to the specified webhook.
167
+
168
+ ## 8. Best Practices
169
+
170
+ - Always validate and sanitize user input to prevent code injection attacks.
171
+ - Set an appropriate timeout value based on the expected execution time of the code.
172
+ - Monitor the execution logs for any errors or unexpected behavior.
173
+ - Implement rate limiting or queue management to prevent abuse or overload of the endpoint.
174
+ - Consider implementing additional security measures, such as code sandboxing or whitelisting/blacklisting certain operations or modules.
docs/ffmpeg/ffmpeg_compose.md ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # FFmpeg Compose API Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/ffmpeg/compose` endpoint is a flexible and powerful API that allows users to compose complex FFmpeg commands by providing input files, filters, and output options. This endpoint is part of the version 1.0 API structure, as shown in the `app.py` file. It is designed to handle various media processing tasks, such as video and audio manipulation, transcoding, and more.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/ffmpeg/compose`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body should be a JSON object with the following properties:
21
+
22
+ - `inputs` (required, array): An array of input file objects, each containing:
23
+ - `file_url` (required, string): The URL of the input file.
24
+ - `options` (optional, array): An array of option objects, each containing:
25
+ - `option` (required, string): The FFmpeg option.
26
+ - `argument` (optional, string, number, or null): The argument for the option.
27
+ - `filters` (optional, array): An array of filter objects, each containing:
28
+ - `filter` (required, string): The FFmpeg filter.
29
+ - `outputs` (required, array): An array of output option objects, each containing:
30
+ - `options` (required, array): An array of option objects, each containing:
31
+ - `option` (required, string): The FFmpeg option.
32
+ - `argument` (optional, string, number, or null): The argument for the option.
33
+ - `global_options` (optional, array): An array of global option objects, each containing:
34
+ - `option` (required, string): The FFmpeg global option.
35
+ - `argument` (optional, string, number, or null): The argument for the option.
36
+ - `metadata` (optional, object): An object specifying which metadata to include in the response, with the following properties:
37
+ - `thumbnail` (optional, boolean): Whether to include a thumbnail for the output file.
38
+ - `filesize` (optional, boolean): Whether to include the file size of the output file.
39
+ - `duration` (optional, boolean): Whether to include the duration of the output file.
40
+ - `bitrate` (optional, boolean): Whether to include the bitrate of the output file.
41
+ - `encoder` (optional, boolean): Whether to include the encoder used for the output file.
42
+ - `webhook_url` (required, string): The URL to send the response webhook.
43
+ - `id` (required, string): A unique identifier for the request.
44
+
45
+ ### Example Request
46
+
47
+ ```json
48
+ {
49
+ "inputs": [
50
+ {
51
+ "file_url": "https://example.com/video1.mp4",
52
+ "options": [
53
+ {
54
+ "option": "-ss",
55
+ "argument": 10
56
+ },
57
+ {
58
+ "option": "-t",
59
+ "argument": 20
60
+ }
61
+ ]
62
+ },
63
+ {
64
+ "file_url": "https://example.com/video2.mp4"
65
+ }
66
+ ],
67
+ "filters": [
68
+ {
69
+ "filter": "hflip"
70
+ }
71
+ ],
72
+ "outputs": [
73
+ {
74
+ "options": [
75
+ {
76
+ "option": "-c:v",
77
+ "argument": "libx264"
78
+ },
79
+ {
80
+ "option": "-crf",
81
+ "argument": 23
82
+ }
83
+ ]
84
+ }
85
+ ],
86
+ "global_options": [
87
+ {
88
+ "option": "-y"
89
+ }
90
+ ],
91
+ "metadata": {
92
+ "thumbnail": true,
93
+ "filesize": true,
94
+ "duration": true,
95
+ "bitrate": true,
96
+ "encoder": true
97
+ },
98
+ "webhook_url": "https://example.com/webhook",
99
+ "id": "unique-request-id"
100
+ }
101
+ ```
102
+
103
+ ```bash
104
+ curl -X POST \
105
+ https://api.example.com/v1/ffmpeg/compose \
106
+ -H 'x-api-key: YOUR_API_KEY' \
107
+ -H 'Content-Type: application/json' \
108
+ -d '{
109
+ "inputs": [
110
+ {
111
+ "file_url": "https://example.com/video1.mp4",
112
+ "options": [
113
+ {
114
+ "option": "-ss",
115
+ "argument": 10
116
+ },
117
+ {
118
+ "option": "-t",
119
+ "argument": 20
120
+ }
121
+ ]
122
+ },
123
+ {
124
+ "file_url": "https://example.com/video2.mp4"
125
+ }
126
+ ],
127
+ "filters": [
128
+ {
129
+ "filter": "hflip"
130
+ }
131
+ ],
132
+ "outputs": [
133
+ {
134
+ "options": [
135
+ {
136
+ "option": "-c:v",
137
+ "argument": "libx264"
138
+ },
139
+ {
140
+ "option": "-crf",
141
+ "argument": 23
142
+ }
143
+ ]
144
+ }
145
+ ],
146
+ "global_options": [
147
+ {
148
+ "option": "-y"
149
+ }
150
+ ],
151
+ "metadata": {
152
+ "thumbnail": true,
153
+ "filesize": true,
154
+ "duration": true,
155
+ "bitrate": true,
156
+ "encoder": true
157
+ },
158
+ "webhook_url": "https://example.com/webhook",
159
+ "id": "unique-request-id"
160
+ }'
161
+ ```
162
+
163
+ ## 4. Response
164
+
165
+ ### Success Response
166
+
167
+ The response will be sent to the specified `webhook_url` as a JSON object with the following properties:
168
+
169
+ - `endpoint` (string): The endpoint URL (`/v1/ffmpeg/compose`).
170
+ - `code` (number): The HTTP status code (200 for success).
171
+ - `id` (string): The unique identifier for the request.
172
+ - `job_id` (string): The unique job ID assigned to the request.
173
+ - `response` (array): An array of output file objects, each containing:
174
+ - `file_url` (string): The URL of the uploaded output file.
175
+ - `thumbnail_url` (string, optional): The URL of the uploaded thumbnail, if requested.
176
+ - `filesize` (number, optional): The file size of the output file, if requested.
177
+ - `duration` (number, optional): The duration of the output file, if requested.
178
+ - `bitrate` (number, optional): The bitrate of the output file, if requested.
179
+ - `encoder` (string, optional): The encoder used for the output file, if requested.
180
+ - `message` (string): The success message ("success").
181
+ - `pid` (number): The process ID of the worker that processed the request.
182
+ - `queue_id` (number): The ID of the queue used for processing the request.
183
+ - `run_time` (number): The time taken to process the request (in seconds).
184
+ - `queue_time` (number): The time the request spent in the queue (in seconds).
185
+ - `total_time` (number): The total time taken to process the request, including queue time (in seconds).
186
+ - `queue_length` (number): The current length of the processing queue.
187
+ - `build_number` (string): The build number of the application.
188
+
189
+ ### Error Responses
190
+
191
+ - **400 Bad Request**: The request payload is invalid or missing required parameters.
192
+ - **401 Unauthorized**: The provided API key is invalid or missing.
193
+ - **429 Too Many Requests**: The maximum queue length has been reached.
194
+ - **500 Internal Server Error**: An unexpected error occurred while processing the request.
195
+
196
+ Example error response:
197
+
198
+ ```json
199
+ {
200
+ "code": 400,
201
+ "id": "unique-request-id",
202
+ "job_id": "job-id",
203
+ "message": "Invalid request payload: 'inputs' is a required property",
204
+ "pid": 123,
205
+ "queue_id": 456,
206
+ "queue_length": 0,
207
+ "build_number": "1.0.0"
208
+ }
209
+ ```
210
+
211
+ ## 5. Error Handling
212
+
213
+ The API handles various types of errors, including:
214
+
215
+ - **Missing or invalid parameters**: If the request payload is missing required parameters or contains invalid data types, a 400 Bad Request error will be returned.
216
+ - **Authentication failure**: If the provided API key is invalid or missing, a 401 Unauthorized error will be returned.
217
+ - **Queue limit reached**: If the maximum queue length is reached, a 429 Too Many Requests error will be returned.
218
+ - **Unexpected errors**: If an unexpected error occurs during request processing, a 500 Internal Server Error will be returned.
219
+
220
+ The main application context (`app.py`) includes error handling for the processing queue. If the maximum queue length is set and the queue size reaches that limit, new requests will be rejected with a 429 Too Many Requests error.
221
+
222
+ ## 6. Usage Notes
223
+
224
+ - The `inputs` array must contain at least one input file object.
225
+ - The `outputs` array must contain at least one output option object.
226
+ - The `filters` array is optional and can be used to apply FFmpeg filters to the input files.
227
+ - The `global_options` array is optional and can be used to specify global FFmpeg options.
228
+ - The `metadata` object is optional and can be used to request specific metadata for the output files.
229
+ - The `webhook_url` parameter is required and specifies the URL where the response should be sent.
230
+ - The `id` parameter is required and should be a unique identifier for the request.
231
+
232
+ ## 7. Common Issues
233
+
234
+ - Providing invalid or malformed input file URLs.
235
+ - Specifying invalid or unsupported FFmpeg options or filters.
236
+ - Reaching the maximum queue length, resulting in a 429 Too Many Requests error.
237
+ - Network or connectivity issues that prevent the response webhook from being delivered.
238
+
239
+ ## 8. Best Practices
240
+
241
+ - Validate input file URLs and ensure they are accessible before sending the request.
242
+ - Test your FFmpeg command locally before using the API to ensure it works as expected.
243
+ - Monitor the queue length and adjust the maximum queue length as needed to prevent overloading the system.
244
+ - Implement retry mechanisms for handling failed webhook deliveries or other transient errors.
245
+ - Use unique and descriptive `id` values for each request to aid in troubleshooting and monitoring.
docs/image/convert/image_to_video.md ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Image to Video Conversion
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/image/convert/video` endpoint is part of the Flask API application and is responsible for converting an image into a video file. This endpoint is registered in the `app.py` file under the `v1_image_convert_video_bp` blueprint, which is imported from the `routes.v1.image.convert.image_to_video` module.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/image/convert/video`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be in JSON format and should include the following parameters:
21
+
22
+ | Parameter | Type | Required | Description |
23
+ |-------------|--------|----------|--------------------------------------------------------------|
24
+ | `image_url` | string | Yes | The URL of the image to be converted into a video. |
25
+ | `length` | number | No | The desired length of the video in seconds (default: 5). |
26
+ | `frame_rate`| integer| No | The frame rate of the output video (default: 30). |
27
+ | `zoom_speed`| number | No | The speed of the zoom effect (0-100, default: 3). |
28
+ | `webhook_url`| string| No | The URL to receive a webhook notification upon completion. |
29
+ | `id` | string | No | An optional identifier for the request. |
30
+
31
+ The `validate_payload` decorator in the `routes.v1.image.convert.image_to_video` module enforces the following JSON schema for the request body:
32
+
33
+ ```json
34
+ {
35
+ "type": "object",
36
+ "properties": {
37
+ "image_url": {"type": "string", "format": "uri"},
38
+ "length": {"type": "number", "minimum": 1, "maximum": 60},
39
+ "frame_rate": {"type": "integer", "minimum": 15, "maximum": 60},
40
+ "zoom_speed": {"type": "number", "minimum": 0, "maximum": 100},
41
+ "webhook_url": {"type": "string", "format": "uri"},
42
+ "id": {"type": "string"}
43
+ },
44
+ "required": ["image_url"],
45
+ "additionalProperties": false
46
+ }
47
+ ```
48
+
49
+ ### Example Request
50
+
51
+ ```json
52
+ {
53
+ "image_url": "https://example.com/image.jpg",
54
+ "length": 10,
55
+ "frame_rate": 24,
56
+ "zoom_speed": 5,
57
+ "webhook_url": "https://example.com/webhook",
58
+ "id": "request-123"
59
+ }
60
+ ```
61
+
62
+ ```bash
63
+ curl -X POST \
64
+ -H "x-api-key: YOUR_API_KEY" \
65
+ -H "Content-Type: application/json" \
66
+ -d '{"image_url": "https://example.com/image.jpg", "length": 10, "frame_rate": 24, "zoom_speed": 5, "webhook_url": "https://example.com/webhook", "id": "request-123"}' \
67
+ http://your-api-endpoint/v1/image/convert/video
68
+ ```
69
+
70
+ ## 4. Response
71
+
72
+ ### Success Response
73
+
74
+ Upon successful processing, the endpoint returns a JSON response with the following structure:
75
+
76
+ ```json
77
+ {
78
+ "code": 200,
79
+ "id": "request-123",
80
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
81
+ "response": "https://cloud-storage.example.com/converted-video.mp4",
82
+ "message": "success",
83
+ "run_time": 2.345,
84
+ "queue_time": 0.123,
85
+ "total_time": 2.468,
86
+ "pid": 12345,
87
+ "queue_id": 1234567890,
88
+ "queue_length": 0,
89
+ "build_number": "1.0.0"
90
+ }
91
+ ```
92
+
93
+ The `response` field contains the URL of the converted video file uploaded to cloud storage.
94
+
95
+ ### Error Responses
96
+
97
+ #### 429 Too Many Requests
98
+
99
+ If the maximum queue length is reached, the endpoint returns a 429 Too Many Requests response:
100
+
101
+ ```json
102
+ {
103
+ "code": 429,
104
+ "id": "request-123",
105
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
106
+ "message": "MAX_QUEUE_LENGTH (10) reached",
107
+ "pid": 12345,
108
+ "queue_id": 1234567890,
109
+ "queue_length": 10,
110
+ "build_number": "1.0.0"
111
+ }
112
+ ```
113
+
114
+ #### 500 Internal Server Error
115
+
116
+ If an exception occurs during the image-to-video conversion process, the endpoint returns a 500 Internal Server Error response:
117
+
118
+ ```json
119
+ {
120
+ "code": 500,
121
+ "id": "request-123",
122
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
123
+ "message": "Error message describing the exception",
124
+ "pid": 12345,
125
+ "queue_id": 1234567890,
126
+ "queue_length": 0,
127
+ "build_number": "1.0.0"
128
+ }
129
+ ```
130
+
131
+ ## 5. Error Handling
132
+
133
+ The endpoint handles the following types of errors:
134
+
135
+ - **Missing or invalid parameters**: If the request body is missing required parameters or contains invalid parameter values, the `validate_payload` decorator will return a 400 Bad Request response with a descriptive error message.
136
+ - **Queue length exceeded**: If the maximum queue length is reached and the `bypass_queue` parameter is set to `False`, the endpoint returns a 429 Too Many Requests response.
137
+ - **Exceptions during processing**: If an exception occurs during the image-to-video conversion process, the endpoint returns a 500 Internal Server Error response with the error message.
138
+
139
+ ## 6. Usage Notes
140
+
141
+ - The `image_url` parameter must be a valid URL pointing to an image file.
142
+ - The `length` parameter specifies the duration of the output video in seconds and must be between 1 and 60.
143
+ - The `frame_rate` parameter specifies the frame rate of the output video and must be between 15 and 60.
144
+ - The `zoom_speed` parameter controls the speed of the zoom effect and must be between 0 and 100.
145
+ - The `webhook_url` parameter is optional and can be used to receive a notification when the conversion is complete.
146
+ - The `id` parameter is optional and can be used to identify the request.
147
+
148
+ ## 7. Common Issues
149
+
150
+ - Providing an invalid or inaccessible `image_url` will result in an error during processing.
151
+ - Specifying invalid parameter values outside the allowed ranges will result in a 400 Bad Request response.
152
+ - If the maximum queue length is reached and the `bypass_queue` parameter is set to `False`, the request will be rejected with a 429 Too Many Requests response.
153
+
154
+ ## 8. Best Practices
155
+
156
+ - Validate the `image_url` parameter before sending the request to ensure it points to a valid and accessible image file.
157
+ - Use the `webhook_url` parameter to receive notifications about the completion of the conversion process, rather than polling the API repeatedly.
158
+ - Provide the `id` parameter to easily identify and track the request in logs or notifications.
159
+ - Consider setting the `bypass_queue` parameter to `True` for time-sensitive requests to bypass the queue and process the request immediately.
docs/image/screenshot_webpage.md ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Playwright Screenshot Endpoint
2
+
3
+ **Implemented by:** [Harrison Fisher](https://github.com/HarrisonFisher)
4
+
5
+ ## ⚠️ Disclaimer
6
+ - This endpoint is **not intended to bypass CAPTCHAs, Cloudflare**, or other anti-bot protections.
7
+ - Please **do not create issues or requests** asking for CAPTCHA or Cloudflare bypass features.
8
+ - It will not work for sites with such defenses, and attempting to automate against protected sites could result in your IP address being blacklisted by Cloudflare or similar services.
9
+ - The screenshot endpoint supports custom HTML, JavaScript, and CSS input for flexible rendering and automation, as an alternative to using a URL.
10
+ - This feature should only be used on sites you own or have explicit permission to automate.
11
+
12
+
13
+ ## 1. Overview
14
+
15
+ The `/v1/image/screenshot/webpage` endpoint allows you to capture screenshots of web pages using the Playwright browser automation library. It supports advanced options such as viewport size, device emulation, cookies, headers, element targeting, and more. Screenshots are uploaded to cloud storage, and the resulting URL is returned. This endpoint is part of the v1 API suite and is registered in the main Flask application as a blueprint.
16
+
17
+ ## 2. Endpoint
18
+
19
+ - **URL Path:** `/v1/image/screenshot/webpage`
20
+ - **HTTP Method:** `POST`
21
+
22
+ ## 3. Request
23
+
24
+ ### Headers
25
+
26
+ - `x-api-key` (required): Your API key for authentication.
27
+ - `Content-Type`: `application/json`
28
+
29
+ ### Body Parameters
30
+
31
+ The request body must be a JSON object with the following properties:
32
+
33
+ - `url` (string, required): The URL of the web page to capture.
34
+ - `html` (string, optional): Raw HTML content to render and capture.
35
+ **Note:** Either `url` or `html` must be provided, but not both.
36
+ - `viewport_width` (integer, optional): Viewport width in pixels.
37
+ - `viewport_height` (integer, optional): Viewport height in pixels.
38
+ - `full_page` (boolean, optional): Capture the full scrollable page. Default: `false`.
39
+ - `format` (string, optional): Image format, either `png` or `jpeg`. Default: `png`.
40
+ - `delay` (integer, optional): Delay in milliseconds before taking the screenshot.
41
+ - `device_scale_factor` (number, optional): Device scale factor (e.g., 2 for retina).
42
+ - `user_agent` (string, optional): Custom user agent string.
43
+ - `cookies` (array, optional): List of cookies to set. Each cookie is an object with `name`, `value`, and `domain`.
44
+ - `headers` (object, optional): Additional HTTP headers to set.
45
+ - `quality` (integer, optional): JPEG quality (0-100, only for `jpeg` format).
46
+ - `clip` (object, optional): Region to capture, with `x`, `y`, `width`, `height` (all numbers).
47
+ - `timeout` (integer, optional): Navigation timeout in milliseconds. Minimum: 100.
48
+ - `wait_until` (string, optional): When to consider navigation succeeded. One of `load`, `domcontentloaded`, `networkidle`, `networkidle2`. Default: `load`.
49
+ - `wait_for_selector` (string, optional): Wait for a selector before screenshot.
50
+ - `emulate` (object, optional): Emulation options, e.g., `{ "color_scheme": "dark" }`.
51
+ - `omit_background` (boolean, optional): Hide default white background. Default: `false`.
52
+ - `selector` (string, optional): CSS selector for a specific element to screenshot.
53
+ - `webhook_url` (string, optional): If provided, results are sent to this URL asynchronously.
54
+ - `id` (string, optional): Custom identifier for the request.
55
+ - `js` (string, optional): JavaScript code to inject into the page before taking the screenshot.
56
+ - `css` (string, optional): CSS code to inject into the page before taking the screenshot.
57
+
58
+ #### Example Request
59
+
60
+ ```json
61
+ {
62
+ "url": "https://example.com",
63
+ "viewport_width": 1280,
64
+ "viewport_height": 720,
65
+ "js": "document.body.style.background = 'red';",
66
+ "css": "body { font-size: 30px; }",
67
+ "full_page": true,
68
+ "format": "png",
69
+ "delay": 500,
70
+ "device_scale_factor": 2,
71
+ "user_agent": "CustomAgent/1.0",
72
+ "cookies": [
73
+ {
74
+ "name": "test_cookie",
75
+ "value": "test_value",
76
+ "domain": "example.com",
77
+ "path": "/"
78
+ }
79
+ ],
80
+ "headers": {
81
+ "Accept-Language": "en-US,en;q=0.9"
82
+ },
83
+ "quality": 90,
84
+ "clip": {
85
+ "x": 0,
86
+ "y": 0,
87
+ "width": 800,
88
+ "height": 600
89
+ },
90
+ "timeout": 10000,
91
+ "wait_until": "networkidle",
92
+ "wait_for_selector": "#main-content",
93
+ "selector": "#main-content",
94
+ "emulate": {
95
+ "color_scheme": "dark"
96
+ },
97
+ "omit_background": true,
98
+ "webhook_url": "https://your-webhook.com/callback",
99
+ "id": "custom-job-123"
100
+ }
101
+ ```
102
+
103
+ **cURL Example:**
104
+
105
+ ```bash
106
+ curl -X POST \
107
+ -H "x-api-key: YOUR_API_KEY" \
108
+ -H "Content-Type: application/json" \
109
+ -d '{
110
+ "url": "https://example.com",
111
+ "viewport_width": 1280,
112
+ "viewport_height": 720,
113
+ "js": "document.body.style.background = '\''red'\'';",
114
+ "css": "body { font-size: 30px; }",
115
+ "full_page": true,
116
+ "format": "png",
117
+ "delay": 500,
118
+ "device_scale_factor": 2,
119
+ "user_agent": "CustomAgent/1.0",
120
+ "cookies": [
121
+ {"name": "test_cookie", "value": "test_value", "domain": "example.com", "path": "/"}
122
+ ],
123
+ "headers": {"Accept-Language": "en-US,en;q=0.9"},
124
+ "quality": 90,
125
+ "clip": {"x": 0, "y": 0, "width": 800, "height": 600},
126
+ "timeout": 10000,
127
+ "wait_until": "networkidle",
128
+ "wait_for_selector": "#main-content",
129
+ "selector": "#main-content",
130
+ "emulate": {"color_scheme": "dark"},
131
+ "omit_background": true,
132
+ "webhook_url": "https://your-webhook.com/callback",
133
+ "id": "custom-job-123"
134
+ }' \
135
+ https://your-api-endpoint.com/v1/image/screenshot/webpage
136
+ ```
137
+
138
+ ## 4. Response
139
+
140
+ ### Success Response
141
+
142
+ The response is a JSON object containing the cloud storage URL of the screenshot and job metadata. If a `webhook_url` is provided, the result is sent asynchronously to the webhook.
143
+
144
+ ```json
145
+ {
146
+ "endpoint": "/v1/image/screenshot/webpage",
147
+ "code": 200,
148
+ "id": "custom-job-123",
149
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
150
+ "response": "https://cloud.example.com/screenshot.png",
151
+ "message": "success",
152
+ "pid": 12345,
153
+ "queue_id": 140682639937472,
154
+ "run_time": 2.345,
155
+ "queue_time": 0.012,
156
+ "total_time": 2.357,
157
+ "queue_length": 0,
158
+ "build_number": "1.0.0"
159
+ }
160
+ ```
161
+
162
+ ### Error Responses
163
+
164
+ - **400 Bad Request**: Invalid or missing parameters.
165
+ - **401 Unauthorized**: Invalid or missing API key.
166
+ - **429 Too Many Requests**: Queue is full.
167
+ - **500 Internal Server Error**: An error occurred during processing.
168
+
169
+ Example error response:
170
+
171
+ ```json
172
+ {
173
+ "endpoint": "/v1/image/screenshot/webpage",
174
+ "code": 500,
175
+ "id": "custom-job-123",
176
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
177
+ "response": null,
178
+ "message": "Error message details",
179
+ "pid": 12345,
180
+ "queue_id": 140682639937472,
181
+ "run_time": 0.123,
182
+ "queue_time": 0.056,
183
+ "total_time": 0.179,
184
+ "queue_length": 1,
185
+ "build_number": "1.0.0"
186
+ }
187
+ ```
188
+
189
+ ## 5. Error Handling
190
+
191
+ - **Missing or invalid parameters**: Returns 400 with details.
192
+ - **Authentication failure**: Returns 401.
193
+ - **Queue full**: Returns 429.
194
+ - **Processing error**: Returns 500 with error message.
195
+
196
+ ## 6. Usage Notes
197
+
198
+ - If `webhook_url` is provided, the request is processed asynchronously and the result is sent to the webhook.
199
+ - Screenshots are always uploaded to cloud storage; the response contains the file URL.
200
+ - Use `selector` to capture a specific element instead of the full page.
201
+ - The `clip` parameter allows capturing a specific region.
202
+ - The endpoint enforces strict payload validation.
203
+
204
+ ## 7. Common Issues
205
+
206
+ - Invalid or inaccessible URL.
207
+ - Selector not found (if using `wait_for_selector` or `selector`).
208
+ - Cookie domain mismatch.
209
+ - Timeout errors for slow-loading pages.
210
+ - Invalid API key.
211
+
212
+ ## 8. Best Practices
213
+
214
+ - Always validate your input parameters before sending the request.
215
+ - Use unique `id` values for tracking jobs.
216
+ - Monitor queue length and handle 429 errors gracefully.
217
+ - Use HTTPS for all URLs and webhooks.
218
+ - Test your selectors and page state locally before automating screenshots.
docs/media/convert/media_convert.md ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media Convert Endpoint Documentation
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/media/convert` endpoint is part of the Flask API application and is responsible for converting media files (audio or video) from one format to another. This endpoint fits into the overall API structure as a part of the `v1` blueprint, which contains various media-related functionalities.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/media/convert`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+
22
+ - `media_url` (required, string): The URL of the media file to be converted.
23
+ - `format` (required, string): The desired output format for the converted media file.
24
+ - `video_codec` (optional, string): The video codec to be used for the conversion. Default is `libx264`.
25
+ - `video_preset` (optional, string): The video preset to be used for the conversion. Default is `medium`.
26
+ - `video_crf` (optional, number): The Constant Rate Factor (CRF) value for video encoding. Must be between 0 and 51. Default is 23.
27
+ - `audio_codec` (optional, string): The audio codec to be used for the conversion. Default is `aac`.
28
+ - `audio_bitrate` (optional, string): The audio bitrate to be used for the conversion. Default is `128k`.
29
+ - `webhook_url` (optional, string): The URL to receive a webhook notification upon completion of the conversion process.
30
+ - `id` (optional, string): An optional identifier for the conversion request.
31
+
32
+ ### Example Request
33
+
34
+ ```json
35
+ {
36
+ "media_url": "https://example.com/video.mp4",
37
+ "format": "avi",
38
+ "video_codec": "libx264",
39
+ "video_preset": "medium",
40
+ "video_crf": 23,
41
+ "audio_codec": "aac",
42
+ "audio_bitrate": "128k",
43
+ "webhook_url": "https://example.com/webhook",
44
+ "id": "unique-request-id"
45
+ }
46
+ ```
47
+
48
+ ```bash
49
+ curl -X POST \
50
+ https://api.example.com/v1/media/convert \
51
+ -H 'x-api-key: YOUR_API_KEY' \
52
+ -H 'Content-Type: application/json' \
53
+ -d '{
54
+ "media_url": "https://example.com/video.mp4",
55
+ "format": "avi",
56
+ "video_codec": "libx264",
57
+ "video_preset": "medium",
58
+ "video_crf": 23,
59
+ "audio_codec": "aac",
60
+ "audio_bitrate": "128k",
61
+ "webhook_url": "https://example.com/webhook",
62
+ "id": "unique-request-id"
63
+ }'
64
+ ```
65
+
66
+ ## 4. Response
67
+
68
+ ### Success Response
69
+
70
+ The success response will be a JSON object containing the URL of the converted media file uploaded to cloud storage, the endpoint path, and a status code of 200.
71
+
72
+ ```json
73
+ {
74
+ "code": 200,
75
+ "id": "unique-request-id",
76
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
77
+ "response": "https://cloud.example.com/converted-video.avi",
78
+ "message": "success",
79
+ "pid": 12345,
80
+ "queue_id": 1234567890,
81
+ "run_time": 10.234,
82
+ "queue_time": 0.123,
83
+ "total_time": 10.357,
84
+ "queue_length": 0,
85
+ "build_number": "1.0.0"
86
+ }
87
+ ```
88
+
89
+ ### Error Responses
90
+
91
+ - **400 Bad Request**: Returned when the request payload is missing or invalid.
92
+ - **401 Unauthorized**: Returned when the `x-api-key` header is missing or invalid.
93
+ - **500 Internal Server Error**: Returned when an unexpected error occurs during the conversion process.
94
+
95
+ Example error response:
96
+
97
+ ```json
98
+ {
99
+ "code": 400,
100
+ "id": "unique-request-id",
101
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
102
+ "message": "Invalid request payload",
103
+ "pid": 12345,
104
+ "queue_id": 1234567890,
105
+ "queue_length": 0,
106
+ "build_number": "1.0.0"
107
+ }
108
+ ```
109
+
110
+ ## 5. Error Handling
111
+
112
+ The endpoint uses the `validate_payload` decorator to validate the request payload against a JSON schema. If the payload is missing or invalid, a 400 Bad Request error is returned.
113
+
114
+ The `authenticate` decorator is used to ensure that the request includes a valid `x-api-key` header. If the header is missing or invalid, a 401 Unauthorized error is returned.
115
+
116
+ If an unexpected error occurs during the conversion process, a 500 Internal Server Error is returned, and the error is logged.
117
+
118
+ ## 6. Usage Notes
119
+
120
+ - The `media_url` parameter must be a valid URL pointing to the media file to be converted.
121
+ - The `format` parameter must be a valid media format supported by the conversion process.
122
+ - The optional parameters (`video_codec`, `video_preset`, `video_crf`, `audio_codec`, `audio_bitrate`) allow you to customize the conversion settings.
123
+ - If the `webhook_url` parameter is provided, a webhook notification will be sent to the specified URL upon completion of the conversion process.
124
+ - The `id` parameter is optional and can be used to identify the conversion request.
125
+
126
+ ## 7. Common Issues
127
+
128
+ - Providing an invalid or inaccessible `media_url`.
129
+ - Specifying an unsupported `format`.
130
+ - Providing invalid values for the optional parameters (e.g., `video_crf` outside the valid range).
131
+
132
+ ## 8. Best Practices
133
+
134
+ - Always validate the input parameters on the client-side before sending the request.
135
+ - Use the `id` parameter to track and identify conversion requests.
136
+ - Provide a `webhook_url` to receive notifications about the conversion process completion.
137
+ - Monitor the API logs for any errors or issues during the conversion process.
138
+ - Consider implementing rate limiting or queue management to handle high volumes of requests.
docs/media/convert/media_to_mp3.md ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media to MP3 Conversion
2
+
3
+ The `/v1/media/convert/mp3` endpoint is part of the Flask API application and is responsible for converting various media files into MP3 format. This endpoint is registered in the `app.py` file under the `v1_media_convert_mp3_bp` blueprint.
4
+
5
+ ## Endpoint Details
6
+
7
+ **URL Path:** `/v1/media/convert/mp3`
8
+
9
+ ## 1. Overview
10
+
11
+ The `/v1/media/convert/mp3` endpoint is a part of the API's media transformation functionality. It allows users to convert various media files (audio or video) to MP3 format. This endpoint fits into the overall API structure as a part of the `v1` namespace, which represents the first version of the API.
12
+
13
+ ## 2. Endpoint
14
+
15
+ ```
16
+ POST /v1/media/convert/mp3
17
+ ```
18
+
19
+ ## 3. Request
20
+
21
+ ### Headers
22
+
23
+ - `x-api-key` (required): The API key for authentication.
24
+
25
+ ### Body Parameters
26
+
27
+ - `media_url` (required, string): The URL of the media file to be converted.
28
+ - `webhook_url` (optional, string): The URL to receive a webhook notification upon completion.
29
+ - `id` (optional, string): A unique identifier for the request.
30
+ - `bitrate` (optional, string): The desired bitrate for the output MP3 file, in the format `<value>k` (e.g., `128k`). If not provided, defaults to `128k`.
31
+
32
+ The `validate_payload` directive in the routes file enforces the following JSON schema for the request body:
33
+
34
+ ```json
35
+ {
36
+ "type": "object",
37
+ "properties": {
38
+ "media_url": {"type": "string", "format": "uri"},
39
+ "webhook_url": {"type": "string", "format": "uri"},
40
+ "id": {"type": "string"},
41
+ "bitrate": {"type": "string", "pattern": "^[0-9]+k$"}
42
+ },
43
+ "required": ["media_url"],
44
+ "additionalProperties": False
45
+ }
46
+ ```
47
+
48
+ ### Example Request
49
+
50
+ ```json
51
+ {
52
+ "media_url": "https://example.com/video.mp4",
53
+ "webhook_url": "https://example.com/webhook",
54
+ "id": "unique-request-id",
55
+ "bitrate": "192k"
56
+ }
57
+ ```
58
+
59
+ ```bash
60
+ curl -X POST \
61
+ -H "x-api-key: YOUR_API_KEY" \
62
+ -H "Content-Type: application/json" \
63
+ -d '{"media_url": "https://example.com/video.mp4", "webhook_url": "https://example.com/webhook", "id": "unique-request-id", "bitrate": "192k"}' \
64
+ https://your-api-endpoint.com/v1/media/convert/mp3
65
+ ```
66
+
67
+ ## 4. Response
68
+
69
+ ### Success Response
70
+
71
+ The success response follows the general response structure defined in `app.py`. Here's an example:
72
+
73
+ ```json
74
+ {
75
+ "endpoint": "/v1/media/convert/mp3",
76
+ "code": 200,
77
+ "id": "unique-request-id",
78
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
79
+ "response": "https://cloud-storage.example.com/converted-file.mp3",
80
+ "message": "success",
81
+ "pid": 12345,
82
+ "queue_id": 6789,
83
+ "run_time": 5.234,
84
+ "queue_time": 0.123,
85
+ "total_time": 5.357,
86
+ "queue_length": 0,
87
+ "build_number": "1.0.0"
88
+ }
89
+ ```
90
+
91
+ ### Error Responses
92
+
93
+ - **400 Bad Request**: Returned when the request payload is invalid or missing required parameters.
94
+ - **401 Unauthorized**: Returned when the `x-api-key` header is missing or invalid.
95
+ - **500 Internal Server Error**: Returned when an unexpected error occurs during the conversion process.
96
+
97
+ Example error response:
98
+
99
+ ```json
100
+ {
101
+ "code": 400,
102
+ "id": "unique-request-id",
103
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
104
+ "message": "Invalid request payload: 'media_url' is a required property",
105
+ "pid": 12345,
106
+ "queue_id": 6789,
107
+ "queue_length": 0,
108
+ "build_number": "1.0.0"
109
+ }
110
+ ```
111
+
112
+ ## 5. Error Handling
113
+
114
+ The endpoint handles the following common errors:
115
+
116
+ - Missing or invalid `media_url` parameter: Returns a 400 Bad Request error.
117
+ - Invalid `bitrate` parameter: Returns a 400 Bad Request error.
118
+ - Authentication failure: Returns a 401 Unauthorized error.
119
+ - Unexpected exceptions during the conversion process: Returns a 500 Internal Server Error.
120
+
121
+ Additionally, the main application context (`app.py`) includes error handling for queue overload. If the maximum queue length is reached, the endpoint will return a 429 Too Many Requests error.
122
+
123
+ ## 6. Usage Notes
124
+
125
+ - The `media_url` parameter should point to a valid media file (audio or video) that can be converted to MP3 format.
126
+ - If the `webhook_url` parameter is provided, a webhook notification will be sent to the specified URL upon completion of the conversion process.
127
+ - The `id` parameter can be used to uniquely identify the request, which can be helpful for tracking and logging purposes.
128
+ - The `bitrate` parameter allows you to specify the desired bitrate for the output MP3 file. If not provided, the default bitrate of 128k will be used.
129
+
130
+ ## 7. Common Issues
131
+
132
+ - Providing an invalid or inaccessible `media_url`.
133
+ - Attempting to convert unsupported media formats.
134
+ - Exceeding the maximum queue length, resulting in a 429 Too Many Requests error.
135
+
136
+ ## 8. Best Practices
137
+
138
+ - Validate the `media_url` parameter before sending the request to ensure it points to a valid and accessible media file.
139
+ - Consider providing a `webhook_url` parameter to receive notifications about the conversion process completion.
140
+ - Use a unique `id` parameter for each request to facilitate tracking and logging.
141
+ - Implement retry mechanisms in case of transient errors or queue overload situations.
142
+ - Monitor the API logs for any errors or issues during the conversion process.
docs/media/cut.md ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media Cut Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/media/cut` endpoint is part of the Flask API application and is designed to cut specified segments from a media file (video or audio) with optional encoding settings. This endpoint fits into the overall API structure as a part of the `v1` blueprint, which contains various media-related functionalities.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/media/cut`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+
22
+ - `media_url` (required, string): The URL of the media file to be cut.
23
+ - `cuts` (required, array of objects): An array of cut segments, where each object has the following properties:
24
+ - `start` (required, string): The start time of the cut segment in the format `hh:mm:ss.ms`.
25
+ - `end` (required, string): The end time of the cut segment in the format `hh:mm:ss.ms`.
26
+ - `video_codec` (optional, string): The video codec to be used for encoding the output file. Default is `libx264`.
27
+ - `video_preset` (optional, string): The video preset to be used for encoding the output file. Default is `medium`.
28
+ - `video_crf` (optional, number): The Constant Rate Factor (CRF) value for video encoding. Must be between 0 and 51. Default is 23.
29
+ - `audio_codec` (optional, string): The audio codec to be used for encoding the output file. Default is `aac`.
30
+ - `audio_bitrate` (optional, string): The audio bitrate to be used for encoding the output file. Default is `128k`.
31
+ - `webhook_url` (optional, string): The URL to receive a webhook notification upon completion of the task.
32
+ - `id` (optional, string): A unique identifier for the request.
33
+
34
+ ### Example Request
35
+
36
+ ```json
37
+ {
38
+ "media_url": "https://example.com/video.mp4",
39
+ "cuts": [
40
+ {
41
+ "start": "00:00:10.000",
42
+ "end": "00:00:20.000"
43
+ },
44
+ {
45
+ "start": "00:00:30.000",
46
+ "end": "00:00:40.000"
47
+ }
48
+ ],
49
+ "video_codec": "libx264",
50
+ "video_preset": "medium",
51
+ "video_crf": 23,
52
+ "audio_codec": "aac",
53
+ "audio_bitrate": "128k",
54
+ "webhook_url": "https://example.com/webhook",
55
+ "id": "unique-request-id"
56
+ }
57
+ ```
58
+
59
+ ```
60
+ curl -X POST \
61
+ https://api.example.com/v1/media/cut \
62
+ -H 'x-api-key: YOUR_API_KEY' \
63
+ -H 'Content-Type: application/json' \
64
+ -d '{
65
+ "media_url": "https://example.com/video.mp4",
66
+ "cuts": [
67
+ {
68
+ "start": "00:00:10.000",
69
+ "end": "00:00:20.000"
70
+ },
71
+ {
72
+ "start": "00:00:30.000",
73
+ "end": "00:00:40.000"
74
+ }
75
+ ],
76
+ "video_codec": "libx264",
77
+ "video_preset": "medium",
78
+ "video_crf": 23,
79
+ "audio_codec": "aac",
80
+ "audio_bitrate": "128k",
81
+ "webhook_url": "https://example.com/webhook",
82
+ "id": "unique-request-id"
83
+ }'
84
+ ```
85
+
86
+ ## 4. Response
87
+
88
+ ### Success Response
89
+
90
+ The success response follows the general response structure defined in the `app.py` file. Here's an example:
91
+
92
+ ```json
93
+ {
94
+ "code": 200,
95
+ "id": "unique-request-id",
96
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
97
+ "response": {
98
+ "file_url": "https://example.com/output.mp4"
99
+ },
100
+ "message": "success",
101
+ "run_time": 5.234,
102
+ "queue_time": 0.012,
103
+ "total_time": 5.246,
104
+ "pid": 12345,
105
+ "queue_id": 1234567890,
106
+ "queue_length": 0,
107
+ "build_number": "1.0.0"
108
+ }
109
+ ```
110
+
111
+ ### Error Responses
112
+
113
+ - **400 Bad Request**: Returned when the request payload is missing or invalid.
114
+
115
+ ```json
116
+ {
117
+ "code": 400,
118
+ "message": "Invalid request payload"
119
+ }
120
+ ```
121
+
122
+ - **401 Unauthorized**: Returned when the `x-api-key` header is missing or invalid.
123
+
124
+ ```json
125
+ {
126
+ "code": 401,
127
+ "message": "Unauthorized"
128
+ }
129
+ ```
130
+
131
+ - **500 Internal Server Error**: Returned when an unexpected error occurs on the server.
132
+
133
+ ```json
134
+ {
135
+ "code": 500,
136
+ "message": "Internal Server Error"
137
+ }
138
+ ```
139
+
140
+ ## 5. Error Handling
141
+
142
+ The endpoint handles the following common errors:
143
+
144
+ - Missing or invalid request parameters: Returns a 400 Bad Request error.
145
+ - Authentication failure: Returns a 401 Unauthorized error if the `x-api-key` header is missing or invalid.
146
+ - Unexpected exceptions: Returns a 500 Internal Server Error if an unexpected exception occurs during the media cut process.
147
+
148
+ The main application context (`app.py`) also includes error handling for queue overload. If the maximum queue length is reached, the endpoint returns a 429 Too Many Requests error.
149
+
150
+ ## 6. Usage Notes
151
+
152
+ - The `media_url` parameter must be a valid URL pointing to a media file (video or audio).
153
+ - The `cuts` parameter must be an array of objects, where each object specifies a start and end time for a cut segment in the format `hh:mm:ss.ms`.
154
+ - The optional encoding parameters (`video_codec`, `video_preset`, `video_crf`, `audio_codec`, `audio_bitrate`) can be used to customize the output file encoding settings.
155
+ - The `webhook_url` parameter is optional and can be used to receive a webhook notification upon completion of the task.
156
+ - The `id` parameter is optional and can be used to uniquely identify the request.
157
+
158
+ ## 7. Common Issues
159
+
160
+ - Providing an invalid or inaccessible `media_url`.
161
+ - Providing invalid or out-of-range values for the encoding parameters.
162
+ - Providing overlapping or invalid cut segments in the `cuts` parameter.
163
+
164
+ ## 8. Best Practices
165
+
166
+ - Validate the input parameters on the client-side before sending the request.
167
+ - Use the `webhook_url` parameter to receive notifications and handle the response asynchronously.
168
+ - Monitor the `queue_length` parameter in the response to manage the load on the API.
169
+ - Use the `id` parameter to correlate requests and responses for better tracking and debugging.
docs/media/download.md ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media Download API Endpoint Documentation
2
+
3
+ ## Overview
4
+
5
+ The `/v1/BETA/media/download` endpoint provides a powerful interface for downloading media content from various online sources using the yt-dlp library. This endpoint is part of the v1 media services in the API structure, allowing users to download videos, extract audio, and retrieve thumbnails and subtitles from supported platforms. The endpoint handles authentication, request validation, and queues tasks for processing, making it suitable for handling resource-intensive media downloads without blocking the main application thread.
6
+
7
+ ## Endpoint
8
+
9
+ - **URL**: `/v1/BETA/media/download`
10
+ - **Method**: `POST`
11
+ - **Blueprint**: `v1_media_download_bp`
12
+
13
+ ## Request
14
+
15
+ ### Headers
16
+
17
+ - `x-api-key`: Required for authentication (handled by the `@authenticate` decorator)
18
+
19
+ ### Body Parameters
20
+
21
+ #### Required Parameters
22
+
23
+ | Parameter | Type | Description |
24
+ |-----------|------|-------------|
25
+ | `media_url` | string (URI format) | The URL of the media to download |
26
+
27
+ #### Optional Parameters
28
+
29
+ | Parameter | Type | Description |
30
+ |-----------|------|-------------|
31
+ | `webhook_url` | string (URI format) | URL to receive the result when processing is complete |
32
+ | `id` | string | Custom identifier for tracking the request |
33
+ | `cookie` | string | Path to cookie file, URL to cookie file, or cookie string in Netscape format |
34
+ | `cloud_upload` | boolean | When true (default), the downloaded media will be uploaded to cloud storage and a cloud URL will be returned. When false, the direct download URL of the media will be returned instead. |
35
+
36
+ #### Format Options (Optional)
37
+
38
+ ```json
39
+ "format": {
40
+ "quality": "string", // Quality specification (e.g., "best")
41
+ "format_id": "string", // Specific format ID
42
+ "resolution": "string", // Resolution specification (e.g., "720p")
43
+ "video_codec": "string", // Video codec preference
44
+ "audio_codec": "string" // Audio codec preference
45
+ }
46
+ ```
47
+
48
+ #### Audio Options (Optional)
49
+
50
+ ```json
51
+ "audio": {
52
+ "extract": boolean, // Whether to extract audio
53
+ "format": "string", // Audio format (e.g., "mp3", "m4a")
54
+ "quality": "string" // Audio quality specification
55
+ }
56
+ ```
57
+
58
+ #### Thumbnail Options (Optional)
59
+
60
+ ```json
61
+ "thumbnails": {
62
+ "download": boolean, // Whether to download thumbnails
63
+ "download_all": boolean, // Whether to download all available thumbnails
64
+ "formats": ["string"], // Array of thumbnail formats to download
65
+ "convert": boolean, // Whether to convert thumbnails
66
+ "embed_in_audio": boolean // Whether to embed thumbnails in audio files
67
+ }
68
+ ```
69
+
70
+ #### Subtitle Options (Optional)
71
+
72
+ ```json
73
+ "subtitles": {
74
+ "download": boolean, // Whether to download subtitles
75
+ "languages": ["string"], // Array of language codes for subtitles
76
+ "format": "string", // Subtitle format to download (e.g., 'srt', 'vtt', 'json3')
77
+ "cloud_upload": boolean // Whether to upload subtitles to cloud storage (defaults to true)
78
+ }
79
+ ```
80
+
81
+ #### Download Options (Optional)
82
+
83
+ ```json
84
+ "download": {
85
+ "max_filesize": integer, // Maximum file size in bytes
86
+ "rate_limit": "string", // Download rate limit (e.g., "50K")
87
+ "retries": integer // Number of download retry attempts
88
+ }
89
+ ```
90
+
91
+ ### Example Request
92
+
93
+ ```json
94
+ {
95
+ "media_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
96
+ "webhook_url": "https://example.com/webhook",
97
+ "id": "custom-request-123",
98
+ "cookie": "# Netscape HTTP Cookie File\n.youtube.com\tTRUE\t/\tFALSE\t0\tCONSENT\tYES+cb",
99
+ "cloud_upload": true,
100
+ "format": {
101
+ "quality": "best",
102
+ "resolution": "720p"
103
+ },
104
+ "audio": {
105
+ "extract": true,
106
+ "format": "mp3"
107
+ },
108
+ "thumbnails": {
109
+ "download": true
110
+ },
111
+ "subtitles": {
112
+ "download": true,
113
+ "languages": ["en", "es-419"],
114
+ "format": "srt",
115
+ "cloud_upload": true
116
+ }
117
+ }
118
+ ```
119
+
120
+ ### Example cURL Command
121
+
122
+ ```bash
123
+ curl -X POST \
124
+ https://api.example.com/v1/BETA/media/download \
125
+ -H 'Content-Type: application/json' \
126
+ -H 'x-api-key: your-api-key-here' \
127
+ -d '{
128
+ "media_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
129
+ "webhook_url": "https://example.com/webhook",
130
+ "id": "custom-request-123",
131
+ "cookie": "# Netscape HTTP Cookie File\n.youtube.com\tTRUE\t/\tFALSE\t0\tCONSENT\tYES+cb",
132
+ "cloud_upload": true,
133
+ "format": {
134
+ "quality": "best",
135
+ "resolution": "720p"
136
+ },
137
+ "audio": {
138
+ "extract": true,
139
+ "format": "mp3"
140
+ },
141
+ "thumbnails": {
142
+ "download": true
143
+ },
144
+ "subtitles": {
145
+ "download": true,
146
+ "languages": ["en", "es-419"],
147
+ "format": "srt",
148
+ "cloud_upload": true
149
+ }
150
+ }'
151
+ ```
152
+
153
+ ## Response
154
+
155
+ ### Immediate Response (When Using Webhook)
156
+
157
+ When a webhook URL is provided, the API will queue the task and return an immediate response with a 202 status code:
158
+
159
+ ```json
160
+ {
161
+ "code": 202,
162
+ "id": "custom-request-123",
163
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
164
+ "message": "processing",
165
+ "pid": 12345,
166
+ "queue_id": 67890,
167
+ "max_queue_length": "unlimited",
168
+ "queue_length": 3,
169
+ "build_number": "1.0.123"
170
+ }
171
+ ```
172
+
173
+ ### Success Response (When Not Using Webhook or When Webhook Is Called)
174
+
175
+ ```json
176
+ {
177
+ "code": 200,
178
+ "id": "custom-request-123",
179
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
180
+ "response": {
181
+ "media": {
182
+ "media_url": "https://storage.example.com/media/video-123.mp4",
183
+ "title": "Never Gonna Give You Up",
184
+ "format_id": "22",
185
+ "ext": "mp4",
186
+ "resolution": "720p",
187
+ "filesize": 12345678,
188
+ "width": 1280,
189
+ "height": 720,
190
+ "fps": 30,
191
+ "video_codec": "avc1.4d401f",
192
+ "audio_codec": "mp4a.40.2",
193
+ "upload_date": "20090325",
194
+ "duration": 212,
195
+ "view_count": 1234567890,
196
+ "uploader": "Rick Astley",
197
+ "uploader_id": "RickAstleyVEVO",
198
+ "description": "Official music video for Rick Astley - Never Gonna Give You Up"
199
+ },
200
+ "thumbnails": [
201
+ {
202
+ "id": "default",
203
+ "image_url": "https://storage.example.com/media/thumbnail-123.jpg",
204
+ "width": 1280,
205
+ "height": 720,
206
+ "original_format": "jpg",
207
+ "converted": false
208
+ }
209
+ ]
210
+ },
211
+ "message": "success",
212
+ "pid": 12345,
213
+ "queue_id": 67890,
214
+ "run_time": 5.123,
215
+ "queue_time": 0.456,
216
+ "total_time": 5.579,
217
+ "queue_length": 2,
218
+ "build_number": "1.0.123"
219
+ }
220
+ ```
221
+
222
+ ### Error Responses
223
+
224
+ #### Invalid Request (400)
225
+
226
+ ```json
227
+ {
228
+ "code": 400,
229
+ "id": "custom-request-123",
230
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
231
+ "message": "Invalid request: 'media_url' is a required property",
232
+ "pid": 12345,
233
+ "queue_id": 67890,
234
+ "queue_length": 2,
235
+ "build_number": "1.0.123"
236
+ }
237
+ ```
238
+
239
+ #### Authentication Error (401)
240
+
241
+ ```json
242
+ {
243
+ "code": 401,
244
+ "message": "Invalid API key",
245
+ "build_number": "1.0.123"
246
+ }
247
+ ```
248
+
249
+ #### Queue Full (429)
250
+
251
+ ```json
252
+ {
253
+ "code": 429,
254
+ "id": "custom-request-123",
255
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
256
+ "message": "MAX_QUEUE_LENGTH (100) reached",
257
+ "pid": 12345,
258
+ "queue_id": 67890,
259
+ "queue_length": 100,
260
+ "build_number": "1.0.123"
261
+ }
262
+ ```
263
+
264
+ #### Server Error (500)
265
+
266
+ ```json
267
+ {
268
+ "code": 500,
269
+ "id": "custom-request-123",
270
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
271
+ "message": "Error during download process - HTTP Error 403: Forbidden",
272
+ "pid": 12345,
273
+ "queue_id": 67890,
274
+ "queue_length": 2,
275
+ "build_number": "1.0.123"
276
+ }
277
+ ```
278
+
279
+ ## Error Handling
280
+
281
+ The endpoint handles various error scenarios:
282
+
283
+ - **Missing Required Parameters**: Returns a 400 status code with details about the missing parameter
284
+ - **Invalid Parameter Format**: Returns a 400 status code if parameters don't match the expected format
285
+ - **Authentication Failures**: Returns a 401 status code if the API key is invalid or missing
286
+ - **Queue Limits**: Returns a 429 status code if the task queue is full (when MAX_QUEUE_LENGTH is set)
287
+ - **Download Failures**: Returns a 500 status code with details about the download failure
288
+ - **Media Source Errors**: Returns a 500 status code if the media source is unavailable or restricted
289
+
290
+ ## Usage Notes
291
+
292
+ 1. **Webhook Handling**:
293
+ - When providing a `webhook_url`, the request will be queued and processed asynchronously
294
+ - Without a `webhook_url`, the request will be processed synchronously, which may lead to longer response times
295
+
296
+ 2. **Format Selection**:
297
+ - The `format` options allow fine-grained control over the downloaded media quality
298
+ - When multiple format options are specified, they are combined with a '+' separator
299
+
300
+ 3. **Audio Extraction**:
301
+ - Setting `audio.extract` to `true` will extract audio from the media
302
+ - Specify `audio.format` to control the output audio format (e.g., "mp3", "m4a")
303
+
304
+ 4. **Thumbnail Handling**:
305
+ - When `thumbnails.download` is `true`, the API will download and provide URLs for thumbnails
306
+ - Use `thumbnails.download_all` to retrieve all available thumbnails
307
+
308
+ 5. **Rate Limiting**:
309
+ - Use `download.rate_limit` to control download speed (e.g., "50K" for 50 KB/s)
310
+ - This can help prevent IP blocking from some media sources
311
+
312
+ ## Common Issues
313
+
314
+ 1. **Geo-restricted Content**: Some media may be unavailable in certain regions
315
+ 2. **Rate Limiting**: Media sources may rate-limit or block frequent downloads
316
+ 3. **Large File Downloads**: Very large files may time out during download
317
+ 4. **Format Availability**: Not all requested formats may be available for all media sources
318
+ 5. **Webhook Failures**: If the webhook URL is unreachable, you won't receive the final result
319
+ 6. **Queue Overflow**: Requests may be rejected if the processing queue is full
320
+
321
+ ## Best Practices
322
+
323
+ 1. **Use Webhooks for Large Downloads**: Always use webhooks for potentially large or slow downloads to avoid timeout issues
324
+ 2. **Specify Format Constraints**: Be specific about format requirements to avoid unnecessarily large downloads
325
+ 3. **Handle Thumbnails Separately**: For efficiency, only request thumbnails when needed
326
+ 4. **Implement Retry Logic**: Implement client-side retry logic for handling temporary failures
327
+ 5. **Monitor Queue Length**: Check the `queue_length` in responses to gauge system load
328
+ 6. **Use Reasonable Rate Limits**: Set appropriate `download.rate_limit` values to avoid being blocked by media sources
329
+ 7. **Validate Media URLs**: Ensure media URLs are valid and accessible before submitting
330
+ 8. **Store Downloaded Media**: The cloud URLs provided in responses may have expiration times, so download and store important media promptly
docs/media/feedback.md ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media Feedback Portal
2
+
3
+ This endpoint serves a static web page for collecting media feedback.
4
+
5
+ ## Endpoint
6
+
7
+ ```
8
+ GET /v1/media/feedback
9
+ ```
10
+
11
+ ### Authentication
12
+
13
+ This endpoint does not require authentication and is publicly accessible.
14
+
15
+ ### Response
16
+
17
+ Returns the HTML feedback form page.
18
+
19
+ ## Static Files
20
+
21
+ Additional static files (CSS, JavaScript, images) can be accessed at:
22
+
23
+ ```
24
+ GET /v1/media/feedback/<filename>
25
+ ```
26
+
27
+ Replace `<filename>` with the path to the static resource relative to the static directory.
28
+
29
+ ## Development
30
+
31
+ The static website files are stored in:
32
+
33
+ ```
34
+ services/v1/media/feedback/static/
35
+ ```
36
+
37
+ This directory contains:
38
+
39
+ - `index.html` - Main HTML file
40
+ - `css/styles.css` - Stylesheet
41
+ - `js/script.js` - JavaScript code
42
+ - `images/` - Directory for image assets
43
+
44
+ To modify the feedback page, edit these files directly.
docs/media/generate_ass.md ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ASS Subtitle Generation Endpoint (v1)
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/media/generate/ass` endpoint is part of the Media API and is responsible for generating an ASS (Advanced SubStation Alpha) subtitle file from a media file (typically a video or audio). It accepts a media URL and various styling options for the subtitles. The endpoint utilizes the `generate_ass_captions_v1` service to generate the ASS file, which is then uploaded to cloud storage, and the cloud URL is returned in the response.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL:** `/v1/media/generate/ass`
10
+ **Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key`: Required. The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+ > **Note:** `canvas_width` and `canvas_height` are recommended for audio files (e.g., MP3) to control the subtitle canvas size.
22
+
23
+ - `media_url` (string, required): The URL of the media file (video or audio) to generate subtitles for.
24
+ - `canvas_width` (integer, optional): Subtitle canvas width in pixels.
25
+ - `canvas_height` (integer, optional): Subtitle canvas height in pixels.
26
+ - `settings` (object, optional): An object containing various styling options for the subtitles. See the schema below for available options.
27
+ - `replace` (array, optional): An array of objects with `find` and `replace` properties, specifying text replacements to be made in the subtitles.
28
+ - `exclude_time_ranges` (array, optional): List of time ranges to skip when generating subtitles. Each item must be an object with:
29
+ - `start`: (string, required) The start time of the excluded range, as a string timecode in `hh:mm:ss.ms` format (e.g., `00:01:23.456`).
30
+ - `end`: (string, required) The end time, as a string timecode in `hh:mm:ss.ms` format, which must be strictly greater than `start`.
31
+ - `language` (string, optional): The language code for the subtitles (e.g., "en", "fr"). Defaults to "auto".
32
+ - `webhook_url` (string, optional): A URL to receive a webhook notification when the subtitle generation process is complete.
33
+ - `id` (string, optional): An identifier for the request.
34
+
35
+
36
+
37
+ #### Settings Schema
38
+
39
+ ```json
40
+ {
41
+ "type": "object",
42
+ "properties": {
43
+ "line_color": {"type": "string"},
44
+ "word_color": {"type": "string"},
45
+ "outline_color": {"type": "string"},
46
+ "all_caps": {"type": "boolean"},
47
+ "max_words_per_line": {"type": "integer"},
48
+ "x": {"type": "integer"},
49
+ "y": {"type": "integer"},
50
+ "position": {
51
+ "type": "string",
52
+ "enum": [
53
+ "bottom_left", "bottom_center", "bottom_right",
54
+ "middle_left", "middle_center", "middle_right",
55
+ "top_left", "top_center", "top_right"
56
+ ]
57
+ },
58
+ "alignment": {
59
+ "type": "string",
60
+ "enum": ["left", "center", "right"]
61
+ },
62
+ "font_family": {"type": "string"},
63
+ "font_size": {"type": "integer"},
64
+ "bold": {"type": "boolean"},
65
+ "italic": {"type": "boolean"},
66
+ "underline": {"type": "boolean"},
67
+ "strikeout": {"type": "boolean"},
68
+ "style": {
69
+ "type": "string",
70
+ "enum": [
71
+ "classic", // Regular subtitle with all text displayed at once
72
+ "karaoke", // Highlights words sequentially in a karaoke style
73
+ "highlight", // Shows full text but highlights the current word
74
+ "underline", // Shows full text but underlines the current word
75
+ "word_by_word" // Shows one word at a time
76
+ ]
77
+ },
78
+ "outline_width": {"type": "integer"},
79
+ "spacing": {"type": "integer"},
80
+ "angle": {"type": "integer"},
81
+ "shadow_offset": {"type": "integer"}
82
+ },
83
+ "additionalProperties": false
84
+ }
85
+ ```
86
+
87
+ ### Example Requests
88
+
89
+ #### Example 1: Basic Automatic Subtitle Generation
90
+ ```json
91
+ {
92
+ "media_url": "https://example.com/video.mp4"
93
+ }
94
+ ```
95
+ This minimal request will automatically transcribe the media and generate white subtitles at the bottom center.
96
+
97
+ #### Example 2: Custom Styling
98
+ ```json
99
+ {
100
+ "media_url": "https://example.com/video.mp4",
101
+ "settings": {
102
+ "style": "classic",
103
+ "line_color": "#FFFFFF",
104
+ "outline_color": "#000000",
105
+ "position": "bottom_center",
106
+ "alignment": "center",
107
+ "font_family": "Arial",
108
+ "font_size": 24,
109
+ "bold": true
110
+ }
111
+ }
112
+ ```
113
+
114
+ #### Example 3: Karaoke-Style Subtitles with Advanced Options
115
+ ```json
116
+ {
117
+ "media_url": "https://example.com/video.mp4",
118
+ "settings": {
119
+ "line_color": "#FFFFFF",
120
+ "word_color": "#FFFF00",
121
+ "outline_color": "#000000",
122
+ "all_caps": false,
123
+ "max_words_per_line": 10,
124
+ "position": "bottom_center",
125
+ "alignment": "center",
126
+ "font_family": "Arial",
127
+ "font_size": 24,
128
+ "bold": false,
129
+ "italic": false,
130
+ "style": "karaoke",
131
+ "outline_width": 2,
132
+ "shadow_offset": 2
133
+ },
134
+ "replace": [
135
+ {
136
+ "find": "um",
137
+ "replace": ""
138
+ },
139
+ {
140
+ "find": "like",
141
+ "replace": ""
142
+ }
143
+ ],
144
+ "webhook_url": "https://example.com/webhook",
145
+ "id": "request-123",
146
+ "language": "en"
147
+ }
148
+ ```
149
+
150
+ #### Example 4: Excluding Time Ranges from Subtitle Generation
151
+ ```json
152
+ {
153
+ "media_url": "https://example.com/video.mp4",
154
+ "settings": {
155
+ "style": "classic",
156
+ "line_color": "#FFFFFF",
157
+ "outline_color": "#000000",
158
+ "position": "bottom_center",
159
+ "font_family": "Arial",
160
+ "font_size": 24
161
+ },
162
+ "exclude_time_ranges": [
163
+ { "start": "00:00:10.000", "end": "00:00:20.000" },
164
+ { "start": "00:00:30.000", "end": "00:00:40.000" }
165
+ ]
166
+ }
167
+ ```
168
+
169
+ #### Example 5: Generating Subtitles for an MP3 (Audio) File
170
+ ```json
171
+ {
172
+ "canvas_width": 1280,
173
+ "canvas_height": 720,
174
+ "media_url": "https://example.com/audio.mp3",
175
+ "settings": {
176
+ "style": "classic",
177
+ "font_family": "Arial",
178
+ "font_size": 32,
179
+ "line_color": "#FFFFFF",
180
+ "outline_color": "#000000"
181
+ }
182
+ }
183
+ ```
184
+
185
+
186
+ ```bash
187
+ curl -X POST \
188
+ -H "x-api-key: YOUR_API_KEY" \
189
+ -H "Content-Type: application/json" \
190
+ -d '{
191
+ "media_url": "https://example.com/video.mp4",
192
+ "settings": {
193
+ "line_color": "#FFFFFF",
194
+ "word_color": "#FFFF00",
195
+ "outline_color": "#000000",
196
+ "all_caps": false,
197
+ "max_words_per_line": 10,
198
+ "position": "bottom_center",
199
+ "alignment": "center",
200
+ "font_family": "Arial",
201
+ "font_size": 24,
202
+ "style": "karaoke",
203
+ "outline_width": 2
204
+ },
205
+ "replace": [
206
+ {
207
+ "find": "um",
208
+ "replace": ""
209
+ }
210
+ ],
211
+ "id": "custom-request-id"
212
+ }' \
213
+ https://your-api-endpoint.com/v1/media/generate/ass
214
+ ```
215
+
216
+ ## 4. Response
217
+
218
+ ### Success Response
219
+
220
+ The response will be a JSON object with the following properties:
221
+
222
+ - `code` (integer): The HTTP status code (200 for success).
223
+ - `id` (string): The request identifier, if provided in the request.
224
+ - `job_id` (string): A unique identifier for the job.
225
+ - `response` (string): The cloud URL of the generated ASS subtitle file.
226
+ - `message` (string): A success message.
227
+ - `pid` (integer): The process ID of the worker that processed the request.
228
+ - `queue_id` (integer): The ID of the queue used for processing the request.
229
+ - `run_time` (float): The time taken to process the request (in seconds).
230
+ - `queue_time` (float): The time the request spent in the queue (in seconds).
231
+ - `total_time` (float): The total time taken for the request (in seconds).
232
+ - `queue_length` (integer): The current length of the processing queue.
233
+ - `build_number` (string): The build number of the application.
234
+
235
+ Example:
236
+
237
+ ```json
238
+ {
239
+ "code": 200,
240
+ "id": "request-123",
241
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
242
+ "response": "https://cloud.example.com/generated-subtitles.ass",
243
+ "message": "success",
244
+ "pid": 12345,
245
+ "queue_id": 140682639937472,
246
+ "run_time": 2.345,
247
+ "queue_time": 0.010,
248
+ "total_time": 2.355,
249
+ "queue_length": 0,
250
+ "build_number": "1.0.0"
251
+ }
252
+ ```
253
+
254
+ ### Error Responses
255
+
256
+ #### Missing or Invalid Parameters
257
+
258
+ **Status Code:** 400 Bad Request
259
+
260
+ ```json
261
+ {
262
+ "code": 400,
263
+ "id": "request-123",
264
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
265
+ "message": "Missing or invalid parameters",
266
+ "pid": 12345,
267
+ "queue_id": 140682639937472,
268
+ "queue_length": 0,
269
+ "build_number": "1.0.0"
270
+ }
271
+ ```
272
+
273
+ #### Font Error
274
+
275
+ **Status Code:** 400 Bad Request
276
+
277
+ ```json
278
+ {
279
+ "code": 400,
280
+ "error": "The requested font 'InvalidFont' is not available. Please choose from the available fonts.",
281
+ "available_fonts": ["Arial", "Times New Roman", "Courier New", ...],
282
+ "pid": 12345,
283
+ "queue_id": 140682639937472,
284
+ "queue_length": 0,
285
+ "build_number": "1.0.0"
286
+ }
287
+ ```
288
+
289
+ #### Internal Server Error
290
+
291
+ **Status Code:** 500 Internal Server Error
292
+
293
+ ```json
294
+ {
295
+ "code": 500,
296
+ "id": "request-123",
297
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
298
+ "error": "An unexpected error occurred during the subtitle generation process.",
299
+ "pid": 12345,
300
+ "queue_id": 140682639937472,
301
+ "queue_length": 0,
302
+ "build_number": "1.0.0"
303
+ }
304
+ ```
305
+
306
+ ## 5. Error Handling
307
+
308
+ The endpoint handles the following common errors:
309
+
310
+ - **Missing or Invalid Parameters**: If any required parameters are missing or invalid, a 400 Bad Request error is returned with a descriptive error message.
311
+ - **Font Error**: If the requested font is not available, a 400 Bad Request error is returned with a list of available fonts.
312
+ - **Internal Server Error**: If an unexpected error occurs during the subtitle generation process, a 500 Internal Server Error is returned with an error message.
313
+
314
+ Additionally, the main application context (`app.py`) includes error handling for queue overload. If the maximum queue length (`MAX_QUEUE_LENGTH`) is set and the queue size reaches that limit, a 429 Too Many Requests error is returned with a descriptive message.
315
+
316
+ ## 6. Usage Notes
317
+
318
+ - The `media_url` parameter must be a valid URL pointing to a video or audio file.
319
+ - The `settings` parameter allows for customization of the subtitle appearance and behavior:
320
+ - `style` determines how subtitles are displayed, with options including:
321
+ - `classic`: Regular subtitle with all text displayed at once
322
+ - `karaoke`: Highlights words sequentially in a karaoke style as they're spoken
323
+ - `highlight`: Shows the full subtitle text but highlights each word as it's spoken
324
+ - `underline`: Shows the full subtitle text but underlines each word as it's spoken
325
+ - `word_by_word`: Shows only one word at a time
326
+ - `position` can be used to place subtitles in one of nine positions on the screen
327
+ - `alignment` determines text alignment within the position (left, center, right)
328
+ - `font_family` can be any available system font
329
+ - Color options can be set using hex codes (e.g., "#FFFFFF" for white)
330
+ - The `replace` parameter can be used to perform text replacements in the subtitles (useful for correcting words or censoring content).
331
+ - The `webhook_url` parameter is optional and can be used to receive a notification when the subtitle generation process is complete.
332
+ - The `id` parameter is optional and can be used to identify the request in webhook responses.
333
+ - The `language` parameter is optional and can be used to specify the language of the subtitles for transcription. If not provided, the language will be automatically detected.
334
+ - The `exclude_time_ranges` parameter can be used to specify time ranges to be excluded from subtitle generation.
335
+ - If either `canvas_width` or `canvas_height` is provided, both must be provided and must be greater than 0.
336
+
337
+ ## 7. Common Issues
338
+
339
+ - Providing an invalid or inaccessible `media_url`.
340
+ - Requesting an unavailable font in the `settings` object.
341
+ - Using this endpoint with an audio-only file (e.g., MP3) and not providing both `canvas_width` and `canvas_height`. For audio files, you must specify both dimensions to generate a valid ASS subtitle file.
342
+ - Exceeding the maximum queue length, resulting in a 429 Too Many Requests error.
343
+
344
+ ## 8. Best Practices
345
+
346
+ - Validate the `media_url` parameter before sending the request to ensure it points to a valid and accessible media file.
347
+ - Use the `webhook_url` parameter to receive notifications about the subtitle generation process, rather than polling the API for updates.
348
+ - Provide descriptive and meaningful `id` values to easily identify requests in logs and responses.
349
+ - Use the `replace` parameter judiciously to avoid unintended text replacements in the subtitles.
350
+ - Consider caching the generated ASS files for frequently requested media to improve performance and reduce processing time.
docs/media/media_transcribe.md ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media Transcription API Documentation
2
+
3
+ ## Overview
4
+ The Media Transcription endpoint is part of the v1 API suite, providing audio/video transcription and translation capabilities. This endpoint leverages a queuing system for handling long-running transcription tasks, with webhook support for asynchronous processing. It's integrated into the main Flask application as a Blueprint and supports both direct response and cloud storage options for the transcription results.
5
+
6
+ ## Endpoint
7
+ - **URL**: `/v1/media/transcribe`
8
+ - **Method**: `POST`
9
+ - **Blueprint**: `v1_media_transcribe_bp`
10
+
11
+ ## Request
12
+
13
+ ### Headers
14
+ - `x-api-key`: Required. Authentication key for API access.
15
+ - `Content-Type`: Required. Must be `application/json`.
16
+
17
+ ### Body Parameters
18
+
19
+ #### Required Parameters
20
+ - `media_url` (string)
21
+ - Format: URI
22
+ - Description: URL of the media file to be transcribed
23
+
24
+ #### Optional Parameters
25
+ - `task` (string)
26
+ - Allowed values: `"transcribe"`, `"translate"`
27
+ - Default: `"transcribe"`
28
+ - Description: Specifies whether to transcribe or translate the audio
29
+
30
+ - `include_text` (boolean)
31
+ - Default: `true`
32
+ - Description: Include plain text transcription in the response
33
+
34
+ - `include_srt` (boolean)
35
+ - Default: `false`
36
+ - Description: Include SRT format subtitles in the response
37
+
38
+ - `include_segments` (boolean)
39
+ - Default: `false`
40
+ - Description: Include timestamped segments in the response
41
+
42
+ - `word_timestamps` (boolean)
43
+ - Default: `false`
44
+ - Description: Include timestamps for individual words
45
+
46
+ - `response_type` (string)
47
+ - Allowed values: `"direct"`, `"cloud"`
48
+ - Default: `"direct"`
49
+ - Description: Whether to return results directly or as cloud storage URLs
50
+
51
+ - `language` (string)
52
+ - Optional
53
+ - Description: Source language code for transcription
54
+
55
+ - `webhook_url` (string)
56
+ - Format: URI
57
+ - Description: URL to receive the transcription results asynchronously
58
+
59
+ - `id` (string)
60
+ - Description: Custom identifier for the transcription job
61
+
62
+ - `max_words_per_line` (integer)
63
+ - Minimum: 1
64
+ - Description: Controls the maximum number of words per line in the SRT file. When specified, each segment's text will be split into multiple lines with at most the specified number of words per line.
65
+
66
+ ### Example Request
67
+
68
+ ```bash
69
+ curl -X POST "https://api.example.com/v1/media/transcribe" \
70
+ -H "x-api-key: your_api_key" \
71
+ -H "Content-Type: application/json" \
72
+ -d '{
73
+ "media_url": "https://example.com/media/file.mp3",
74
+ "task": "transcribe",
75
+ "include_text": true,
76
+ "include_srt": true,
77
+ "include_segments": true,
78
+ "response_type": "cloud",
79
+ "webhook_url": "https://your-webhook.com/callback",
80
+ "id": "custom-job-123",
81
+ "max_words_per_line": 5
82
+ }'
83
+ ```
84
+
85
+ ## Response
86
+
87
+ ### Immediate Response (202 Accepted)
88
+ When a webhook URL is provided, the API returns an immediate acknowledgment:
89
+
90
+ ```json
91
+ {
92
+ "code": 202,
93
+ "id": "custom-job-123",
94
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
95
+ "message": "processing",
96
+ "pid": 12345,
97
+ "queue_id": 67890,
98
+ "max_queue_length": "unlimited",
99
+ "queue_length": 1,
100
+ "build_number": "1.0.0"
101
+ }
102
+ ```
103
+
104
+ ### Success Response (via Webhook)
105
+ For direct response_type:
106
+
107
+ ```json
108
+ {
109
+ "endpoint": "/v1/transcribe/media",
110
+ "code": 200,
111
+ "id": "custom-job-123",
112
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
113
+ "response": {
114
+ "text": "Transcribed text content...",
115
+ "srt": "SRT formatted content...",
116
+ "segments": [...],
117
+ "text_url": null,
118
+ "srt_url": null,
119
+ "segments_url": null
120
+ },
121
+ "message": "success",
122
+ "pid": 12345,
123
+ "queue_id": 67890,
124
+ "run_time": 5.234,
125
+ "queue_time": 0.123,
126
+ "total_time": 5.357,
127
+ "queue_length": 0,
128
+ "build_number": "1.0.0"
129
+ }
130
+ ```
131
+
132
+ For cloud response_type:
133
+
134
+ ```json
135
+ {
136
+ "endpoint": "/v1/transcribe/media",
137
+ "code": 200,
138
+ "id": "custom-job-123",
139
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
140
+ "response": {
141
+ "text": null,
142
+ "srt": null,
143
+ "segments": null,
144
+ "text_url": "https://storage.example.com/text.txt",
145
+ "srt_url": "https://storage.example.com/subtitles.srt",
146
+ "segments_url": "https://storage.example.com/segments.json"
147
+ },
148
+ "message": "success",
149
+ "pid": 12345,
150
+ "queue_id": 67890,
151
+ "run_time": 5.234,
152
+ "queue_time": 0.123,
153
+ "total_time": 5.357,
154
+ "queue_length": 0,
155
+ "build_number": "1.0.0"
156
+ }
157
+ ```
158
+
159
+ ### Error Responses
160
+
161
+ #### Queue Full (429 Too Many Requests)
162
+ ```json
163
+ {
164
+ "code": 429,
165
+ "id": "custom-job-123",
166
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
167
+ "message": "MAX_QUEUE_LENGTH (100) reached",
168
+ "pid": 12345,
169
+ "queue_id": 67890,
170
+ "queue_length": 100,
171
+ "build_number": "1.0.0"
172
+ }
173
+ ```
174
+
175
+ #### Server Error (500 Internal Server Error)
176
+ ```json
177
+ {
178
+ "endpoint": "/v1/transcribe/media",
179
+ "code": 500,
180
+ "id": "custom-job-123",
181
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
182
+ "response": null,
183
+ "message": "Error message details",
184
+ "pid": 12345,
185
+ "queue_id": 67890,
186
+ "run_time": 0.123,
187
+ "queue_time": 0.056,
188
+ "total_time": 0.179,
189
+ "queue_length": 1,
190
+ "build_number": "1.0.0"
191
+ }
192
+ ```
193
+
194
+ ## Error Handling
195
+
196
+ ### Common Errors
197
+ - **Invalid API Key**: 401 Unauthorized
198
+ - **Invalid JSON Payload**: 400 Bad Request
199
+ - **Missing Required Fields**: 400 Bad Request
200
+ - **Invalid media_url**: 400 Bad Request
201
+ - **Queue Full**: 429 Too Many Requests
202
+ - **Processing Error**: 500 Internal Server Error
203
+
204
+ ### Validation Errors
205
+ The endpoint performs strict validation of the request payload using JSON Schema. Common validation errors include:
206
+ - Invalid URI format for media_url or webhook_url
207
+ - Invalid task value (must be "transcribe" or "translate")
208
+ - Invalid response_type value (must be "direct" or "cloud")
209
+ - Unknown properties in the request body
210
+
211
+ ## Usage Notes
212
+
213
+ 1. **Webhook Processing**
214
+ - When a webhook_url is provided, the request is processed asynchronously
215
+ - The API returns an immediate 202 response with a job_id
216
+ - Final results are sent to the webhook_url when processing completes
217
+
218
+ 2. **Queue Management**
219
+ - Requests with webhook_url are queued for processing
220
+ - MAX_QUEUE_LENGTH environment variable controls queue size
221
+ - Set MAX_QUEUE_LENGTH to 0 for unlimited queue size
222
+
223
+ 3. **File Management**
224
+ - For cloud response_type, temporary files are automatically cleaned up
225
+ - Results are uploaded to cloud storage before deletion
226
+ - URLs in the response provide access to the stored files
227
+
228
+ 4. **SRT Formatting**
229
+ - The `max_words_per_line` parameter allows control over the maximum number of words per line in the SRT file
230
+ - When specified, each segment's text will be split into multiple lines with at most the specified number of words per line
231
+ - This is useful for creating more readable subtitles with consistent line lengths
232
+
233
+ ## Common Issues
234
+
235
+ 1. **Media Access**
236
+ - Ensure media_url is publicly accessible
237
+ - Verify media file format is supported
238
+ - Check for media file corruption
239
+
240
+ 2. **Webhook Delivery**
241
+ - Ensure webhook_url is publicly accessible
242
+ - Implement webhook endpoint retry logic
243
+ - Monitor webhook endpoint availability
244
+
245
+ 3. **Resource Usage**
246
+ - Large media files may take significant processing time
247
+ - Monitor queue length for production deployments
248
+ - Consider implementing request size limits
249
+
250
+ ## Best Practices
251
+
252
+ 1. **Request Handling**
253
+ - Always provide a unique id for job tracking
254
+ - Implement webhook retry logic
255
+ - Store job_id for result correlation
256
+
257
+ 2. **Resource Management**
258
+ - Monitor queue length in production
259
+ - Implement appropriate timeout handling
260
+ - Use cloud response_type for large files
261
+
262
+ 3. **Error Handling**
263
+ - Implement comprehensive webhook error handling
264
+ - Log job_id with all related operations
265
+ - Monitor processing times and error rates
266
+
267
+ 4. **Security**
268
+ - Use HTTPS for media_url and webhook_url
269
+ - Implement webhook authentication
270
+ - Validate media file types before processing
docs/media/metadata.md ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Media Metadata
2
+
3
+ This endpoint extracts detailed metadata from media files (video, audio, image) including format, duration, codec information, resolution, and bitrates.
4
+
5
+ ## Endpoint
6
+
7
+ `POST /v1/media/metadata`
8
+
9
+ ## Authentication
10
+
11
+ This endpoint requires API authentication. See [Authentication](../toolkit/authenticate.md) for details.
12
+
13
+ ## Request
14
+
15
+ ```json
16
+ {
17
+ "media_url": "https://example.com/media.mp4",
18
+ "webhook_url": "https://example.com/webhook", // Optional
19
+ "id": "custom-id" // Optional
20
+ }
21
+ ```
22
+
23
+ | Parameter | Type | Required | Description |
24
+ |-----------|------|----------|-------------|
25
+ | media_url | string | Yes | URL of the media file to analyze |
26
+ | webhook_url | string | No | URL to receive the processing result |
27
+ | id | string | No | Custom identifier for tracking the request |
28
+
29
+ ## Response
30
+
31
+ **Success (200 OK)**
32
+
33
+ ```json
34
+ {
35
+ "code": 200,
36
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
37
+ "id": "custom-id",
38
+ "response": {
39
+ "filesize": 15679283,
40
+ "filesize_mb": 14.95,
41
+ "duration": 87.46,
42
+ "duration_formatted": "00:01:27.46",
43
+ "format": "mp4,mov,m4a,3gp,3g2,mj2",
44
+ "overall_bitrate": 1438692,
45
+ "overall_bitrate_mbps": 1.44,
46
+ "has_video": true,
47
+ "video_codec": "h264",
48
+ "video_codec_long": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
49
+ "width": 1920,
50
+ "height": 1080,
51
+ "resolution": "1920x1080",
52
+ "fps": 30.0,
53
+ "video_bitrate": 1300000,
54
+ "video_bitrate_mbps": 1.3,
55
+ "pixel_format": "yuv420p",
56
+ "has_audio": true,
57
+ "audio_codec": "aac",
58
+ "audio_codec_long": "AAC (Advanced Audio Coding)",
59
+ "audio_channels": 2,
60
+ "audio_sample_rate": 48000,
61
+ "audio_sample_rate_khz": 48.0,
62
+ "audio_bitrate": 128000,
63
+ "audio_bitrate_kbps": 128
64
+ },
65
+ "message": "success",
66
+ "run_time": 0.542,
67
+ "queue_time": 0,
68
+ "total_time": 0.542,
69
+ "pid": 12345,
70
+ "queue_id": 67890,
71
+ "queue_length": 0,
72
+ "build_number": "123"
73
+ }
74
+ ```
75
+
76
+ For audio-only files, video-related fields will not be included. Similarly, for video files without audio, audio-related fields will not be included.
77
+
78
+ **Queued (202 Accepted)**
79
+
80
+ ```json
81
+ {
82
+ "code": 202,
83
+ "id": "custom-id",
84
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
85
+ "message": "processing",
86
+ "pid": 12345,
87
+ "queue_id": 67890,
88
+ "max_queue_length": "unlimited",
89
+ "queue_length": 0,
90
+ "build_number": "123"
91
+ }
92
+ ```
93
+
94
+ **Error (4xx/5xx)**
95
+
96
+ ```json
97
+ {
98
+ "code": 500,
99
+ "id": "custom-id",
100
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
101
+ "message": "Error extracting metadata: [error details]",
102
+ "pid": 12345,
103
+ "queue_id": 67890,
104
+ "queue_length": 0,
105
+ "build_number": "123"
106
+ }
107
+ ```
108
+
109
+ ## Example
110
+
111
+ ### Request
112
+
113
+ ```bash
114
+ curl -X POST https://api.example.com/v1/media/metadata \
115
+ -H "Content-Type: application/json" \
116
+ -H "Authorization: Bearer your_api_key" \
117
+ -d '{
118
+ "media_url": "https://example.com/sample-video.mp4",
119
+ "webhook_url": "https://your-server.com/webhook"
120
+ }'
121
+ ```
122
+
123
+ ### Response
124
+
125
+ ```json
126
+ {
127
+ "code": 200,
128
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
129
+ "response": {
130
+ "filesize": 15679283,
131
+ "filesize_mb": 14.95,
132
+ "duration": 87.46,
133
+ "duration_formatted": "00:01:27.46",
134
+ "format": "mp4",
135
+ "overall_bitrate": 1438692,
136
+ "overall_bitrate_mbps": 1.44,
137
+ "has_video": true,
138
+ "video_codec": "h264",
139
+ "width": 1920,
140
+ "height": 1080,
141
+ "resolution": "1920x1080",
142
+ "fps": 30.0,
143
+ "video_bitrate": 1300000,
144
+ "video_bitrate_mbps": 1.3,
145
+ "has_audio": true,
146
+ "audio_codec": "aac",
147
+ "audio_channels": 2,
148
+ "audio_sample_rate": 48000,
149
+ "audio_bitrate": 128000,
150
+ "audio_bitrate_kbps": 128
151
+ },
152
+ "message": "success",
153
+ "run_time": 0.542,
154
+ "total_time": 0.542
155
+ }
156
+ ```
docs/media/silence.md ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Silence Detection Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/media/silence` endpoint is part of the Media API and is designed to detect silence intervals in a given media file. It takes a media URL, along with various parameters for configuring the silence detection process, and returns the detected silence intervals. This endpoint fits into the overall API structure as a part of the version 1 (v1) media-related endpoints.
6
+
7
+ ## 2. Endpoint
8
+
9
+ ```
10
+ POST /v1/media/silence
11
+ ```
12
+
13
+ ## 3. Request
14
+
15
+ ### Headers
16
+
17
+ - `x-api-key` (required): The API key for authentication.
18
+
19
+ ### Body Parameters
20
+
21
+ The request body should be a JSON object with the following parameters:
22
+
23
+ - `media_url` (required, string): The URL of the media file to be processed.
24
+ - `start` (optional, string): The start time for the silence detection process, in the format `HH:MM:SS.ms`. If not provided, the process will start from the beginning of the media file.
25
+ - `end` (optional, string): The end time for the silence detection process, in the format `HH:MM:SS.ms`. If not provided, the process will continue until the end of the media file.
26
+ - `noise` (optional, string): The noise threshold for silence detection, in decibels (dB). Default is `-30dB`.
27
+ - `duration` (required, number): The minimum duration (in seconds) for a silence interval to be considered valid.
28
+ - `mono` (optional, boolean): Whether to process the audio as mono (single channel) or not. Default is `true`.
29
+ - `webhook_url` (required, string): The URL to which the response should be sent as a webhook.
30
+ - `id` (required, string): A unique identifier for the request.
31
+
32
+ The `validate_payload` directive in the routes file enforces the following JSON schema for the request body:
33
+
34
+ ```python
35
+ {
36
+ "type": "object",
37
+ "properties": {
38
+ "media_url": {"type": "string", "format": "uri"},
39
+ "start": {"type": "string"},
40
+ "end": {"type": "string"},
41
+ "noise": {"type": "string"},
42
+ "duration": {"type": "number", "minimum": 0.1},
43
+ "mono": {"type": "boolean"},
44
+ "webhook_url": {"type": "string", "format": "uri"},
45
+ "id": {"type": "string"}
46
+ },
47
+ "required": ["media_url", "duration"],
48
+ "additionalProperties": False
49
+ }
50
+ ```
51
+
52
+ ### Example Request
53
+
54
+ ```json
55
+ {
56
+ "media_url": "https://example.com/audio.mp3",
57
+ "start": "00:00:10.0",
58
+ "end": "00:01:00.0",
59
+ "noise": "-25dB",
60
+ "duration": 0.5,
61
+ "mono": false,
62
+ "webhook_url": "https://example.com/webhook",
63
+ "id": "unique-request-id"
64
+ }
65
+ ```
66
+
67
+ ```
68
+ curl -X POST \
69
+ https://api.example.com/v1/media/silence \
70
+ -H 'x-api-key: YOUR_API_KEY' \
71
+ -H 'Content-Type: application/json' \
72
+ -d '{
73
+ "media_url": "https://example.com/audio.mp3",
74
+ "start": "00:00:10.0",
75
+ "end": "00:01:00.0",
76
+ "noise": "-25dB",
77
+ "duration": 0.5,
78
+ "mono": false,
79
+ "webhook_url": "https://example.com/webhook",
80
+ "id": "unique-request-id"
81
+ }'
82
+ ```
83
+
84
+ ## 4. Response
85
+
86
+ ### Success Response
87
+
88
+ The success response will be sent as a webhook to the specified `webhook_url`. The response format follows the general response structure defined in the main application context (`app.py`). Here's an example:
89
+
90
+ ```json
91
+ {
92
+ "endpoint": "/v1/media/silence",
93
+ "code": 200,
94
+ "id": "unique-request-id",
95
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
96
+ "response": [
97
+ {
98
+ "start": 10.5,
99
+ "end": 15.2
100
+ },
101
+ {
102
+ "start": 20.0,
103
+ "end": 25.7
104
+ }
105
+ ],
106
+ "message": "success",
107
+ "pid": 12345,
108
+ "queue_id": 1234567890,
109
+ "run_time": 1.234,
110
+ "queue_time": 0.123,
111
+ "total_time": 1.357,
112
+ "queue_length": 0,
113
+ "build_number": "1.0.0"
114
+ }
115
+ ```
116
+
117
+ ### Error Responses
118
+
119
+ - **400 Bad Request**: This error is returned when the request body is missing or contains invalid parameters. Example response:
120
+
121
+ ```json
122
+ {
123
+ "code": 400,
124
+ "message": "Invalid request payload"
125
+ }
126
+ ```
127
+
128
+ - **401 Unauthorized**: This error is returned when the `x-api-key` header is missing or invalid. Example response:
129
+
130
+ ```json
131
+ {
132
+ "code": 401,
133
+ "message": "Unauthorized"
134
+ }
135
+ ```
136
+
137
+ - **500 Internal Server Error**: This error is returned when an unexpected error occurs during the silence detection process. Example response:
138
+
139
+ ```json
140
+ {
141
+ "code": 500,
142
+ "message": "An error occurred during the silence detection process"
143
+ }
144
+ ```
145
+
146
+ ## 5. Error Handling
147
+
148
+ The endpoint handles the following common errors:
149
+
150
+ - Missing or invalid request parameters: Returns a 400 Bad Request error.
151
+ - Missing or invalid `x-api-key` header: Returns a 401 Unauthorized error.
152
+ - Unexpected exceptions during the silence detection process: Returns a 500 Internal Server Error.
153
+
154
+ The main application context (`app.py`) also includes error handling for situations where the task queue has reached its maximum length (`MAX_QUEUE_LENGTH`). In such cases, a 429 Too Many Requests error is returned.
155
+
156
+ ## 6. Usage Notes
157
+
158
+ - The `media_url` parameter should point to a valid media file that can be processed by the silence detection service.
159
+ - The `start` and `end` parameters are optional and can be used to specify a time range within the media file for silence detection.
160
+ - The `noise` parameter allows you to adjust the noise threshold for silence detection. Lower values (e.g., `-40dB`) will detect more silence intervals, while higher values (e.g., `-20dB`) will detect fewer silence intervals.
161
+ - The `duration` parameter specifies the minimum duration (in seconds) for a silence interval to be considered valid. This can be useful for filtering out very short silence intervals that may not be relevant.
162
+ - The `mono` parameter determines whether the audio should be processed as a single channel (mono) or multiple channels (stereo or surround).
163
+
164
+ ## 7. Common Issues
165
+
166
+ - Providing an invalid or inaccessible `media_url`.
167
+ - Specifying `start` and `end` times that are outside the duration of the media file.
168
+ - Setting the `duration` parameter to an unreasonably low value, which may result in detecting too many short silence intervals.
169
+
170
+ ## 8. Best Practices
171
+
172
+ - Validate the `media_url` parameter to ensure it points to a valid and accessible media file.
173
+ - Consider using the `start` and `end` parameters to focus the silence detection on a specific time range within the media file, if needed.
174
+ - Adjust the `noise` and `duration` parameters based on your specific use case and requirements for silence detection.
175
+ - If you need to process stereo or surround audio, set the `mono` parameter to `false`.
176
+ - Monitor the response from the endpoint to ensure that the silence detection process completed successfully and that the detected silence intervals meet your expectations.
docs/s3/upload.md ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # S3 Upload API
2
+
3
+ This endpoint allows you to stream a file from a remote URL directly to an S3-compatible storage service without using local disk space.
4
+
5
+ ## Endpoint
6
+
7
+ `POST /v1/s3/upload`
8
+
9
+ ## Authentication
10
+
11
+ This endpoint requires an API key to be provided in the `X-API-Key` header.
12
+
13
+ ## Request Body
14
+
15
+ The request body should be a JSON object with the following properties:
16
+
17
+ | Property | Type | Required | Description |
18
+ |----------|------|----------|-------------|
19
+ | file_url | string | Yes | The URL of the file to upload to S3 |
20
+ | filename | string | No | Custom filename to use for the uploaded file. If not provided, the original filename will be used |
21
+ | public | boolean | No | Whether to make the file publicly accessible. Defaults to `false` |
22
+
23
+ Example request body:
24
+ ```json
25
+ {
26
+ "file_url": "https://example.com/path/to/file.mp4",
27
+ "filename": "custom-name.mp4",
28
+ "public": true
29
+ }
30
+ ```
31
+
32
+ ## Response
33
+
34
+ The response will be a JSON object with the following properties:
35
+
36
+ | Property | Type | Description |
37
+ |----------|------|-------------|
38
+ | url | string | The URL of the uploaded file. For public files, this is a direct URL. For private files, this is a pre-signed URL that will expire after 1 hour |
39
+ | filename | string | The filename of the uploaded file |
40
+ | bucket | string | The name of the S3 bucket where the file was uploaded |
41
+ | public | boolean | Whether the file is publicly accessible |
42
+
43
+ Example response:
44
+ ```json
45
+ {
46
+ "url": "https://bucket-name.s3.region.amazonaws.com/custom-name.mp4",
47
+ "filename": "custom-name.mp4",
48
+ "bucket": "bucket-name",
49
+ "public": true
50
+ }
51
+ ```
52
+
53
+ ## Error Handling
54
+
55
+ If an error occurs, the response will include an error message with an appropriate HTTP status code.
56
+
57
+ ## Technical Details
58
+
59
+ This endpoint uses the S3-compatible multipart upload API to stream the file directly from the source URL to S3 without saving it locally. This allows for efficient transfer of large files with minimal memory usage.
60
+
61
+ The implementation:
62
+ 1. Streams the file from the source URL in chunks
63
+ 2. Uploads each chunk to S3 as a part of a multipart upload
64
+ 3. Completes the multipart upload once all parts are uploaded
65
+
66
+ This approach supports resumable uploads and can handle large files efficiently.
docs/toolkit/authenticate.md ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Authenticate Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/toolkit/authenticate` endpoint is a part of the `v1_toolkit_auth` blueprint in the API structure. Its purpose is to authenticate requests by verifying the provided API key against a predefined value. This endpoint serves as a gatekeeper, ensuring that only authorized clients can access the API's resources.
6
+
7
+ ## 2. Endpoint
8
+
9
+ - URL Path: `/v1/toolkit/authenticate`
10
+ - HTTP Method: `GET`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `X-API-Key` (required): The API key used for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ This endpoint does not require any request body parameters.
21
+
22
+ ### Example Request
23
+
24
+ ```bash
25
+ curl -X GET -H "X-API-Key: YOUR_API_KEY" http://localhost:8080/v1/toolkit/authenticate
26
+ ```
27
+
28
+ ## 4. Response
29
+
30
+ ### Success Response
31
+
32
+ If the provided API key matches the predefined value, the endpoint will return a 200 OK status code with the following response:
33
+
34
+ ```json
35
+ {
36
+ "code": 200,
37
+ "endpoint": "/authenticate",
38
+ "id": null,
39
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
40
+ "message": "success",
41
+ "pid": 12345,
42
+ "queue_id": 1234567890,
43
+ "queue_length": 0,
44
+ "response": "Authorized",
45
+ "run_time": 0.001,
46
+ "total_time": 0.001,
47
+ "queue_time": 0,
48
+ "build_number": "1.0.0"
49
+ }
50
+ ```
51
+
52
+ ### Error Responses
53
+
54
+ If the provided API key is invalid or missing, the endpoint will return a 401 Unauthorized status code with the following response:
55
+
56
+ ```json
57
+ {
58
+ "code": 401,
59
+ "endpoint": "/authenticate",
60
+ "id": null,
61
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
62
+ "message": "Unauthorized",
63
+ "pid": 12345,
64
+ "queue_id": 1234567890,
65
+ "queue_length": 0,
66
+ "response": null,
67
+ "run_time": 0.001,
68
+ "total_time": 0.001,
69
+ "queue_time": 0,
70
+ "build_number": "1.0.0"
71
+ }
72
+ ```
73
+
74
+ ## 5. Error Handling
75
+
76
+ The main error that can occur with this endpoint is providing an invalid or missing API key. In this case, the endpoint will return a 401 Unauthorized status code with an appropriate error message.
77
+
78
+ ## 6. Usage Notes
79
+
80
+ - This endpoint is designed to be used as a gatekeeper for the API, ensuring that only authorized clients can access the API's resources.
81
+ - The API key should be kept secure and should not be shared with unauthorized parties.
82
+
83
+ ## 7. Common Issues
84
+
85
+ - Forgetting to include the `X-API-Key` header in the request.
86
+ - Using an invalid or expired API key.
87
+
88
+ ## 8. Best Practices
89
+
90
+ - Rotate API keys periodically to enhance security.
91
+ - Store API keys securely and avoid committing them to version control systems.
92
+ - Consider implementing additional security measures, such as rate limiting or IP whitelisting, to further protect the API.
docs/toolkit/job_status.md ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Job Status Endpoint Documentation
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/toolkit/job/status` endpoint is part of the Toolkit API and is used to retrieve the status of a specific job. It fits into the overall API structure as a utility endpoint for monitoring and managing jobs submitted to the various media processing endpoints.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/toolkit/job/status`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following parameter:
21
+
22
+ - `job_id` (string, required): The unique identifier of the job for which the status is requested.
23
+
24
+ The `validate_payload` directive in the routes file enforces the following JSON schema for the request body:
25
+
26
+ ```python
27
+ {
28
+ "type": "object",
29
+ "properties": {
30
+ "job_id": {
31
+ "type": "string"
32
+ }
33
+ },
34
+ "required": ["job_id"],
35
+ }
36
+ ```
37
+
38
+ ### Example Request
39
+
40
+ ```json
41
+ {
42
+ "job_id": "e6d7f3c0-9c9f-4b8a-b7c3-f0e3c9f6b9d7"
43
+ }
44
+ ```
45
+
46
+ ```bash
47
+ curl -X POST \
48
+ -H "x-api-key: YOUR_API_KEY" \
49
+ -H "Content-Type: application/json" \
50
+ -d '{"job_id": "e6d7f3c0-9c9f-4b8a-b7c3-f0e3c9f6b9d7"}' \
51
+ http://your-api-endpoint/v1/toolkit/job/status
52
+ ```
53
+
54
+ ## 4. Response
55
+
56
+ ### Success Response
57
+
58
+ The success response will contain the job status file content directly, as shown in the example response from `app.py`:
59
+
60
+ ```json
61
+ {
62
+ "endpoint": "/v1/toolkit/job/status",
63
+ "code": 200,
64
+ "id": null,
65
+ "job_id": "e6d7f3c0-9c9f-4b8a-b7c3-f0e3c9f6b9d7",
66
+ "response": {
67
+ "job_status": "done",
68
+ "job_id": "e6d7f3c0-9c9f-4b8a-b7c3-f0e3c9f6b9d7",
69
+ "queue_id": 140368864456064,
70
+ "process_id": 123456,
71
+ "response": {
72
+ "endpoint": "/v1/media/transcribe",
73
+ "code": 200,
74
+ "id": "transcribe_job_123",
75
+ "job_id": "e6d7f3c0-9c9f-4b8a-b7c3-f0e3c9f6b9d7",
76
+ "response": "Transcription completed successfully.",
77
+ "message": "success",
78
+ "pid": 123456,
79
+ "queue_id": 140368864456064,
80
+ "run_time": 5.234,
81
+ "queue_time": 1.123,
82
+ "total_time": 6.357,
83
+ "queue_length": 0,
84
+ "build_number": "1.0.0"
85
+ }
86
+ },
87
+ "message": "success",
88
+ "pid": 123456,
89
+ "queue_id": 140368864456064,
90
+ "run_time": 0.001,
91
+ "queue_time": 0.0,
92
+ "total_time": 0.001,
93
+ "queue_length": 0,
94
+ "build_number": "1.0.0"
95
+ }
96
+ ```
97
+
98
+ ### Error Responses
99
+
100
+ - **404 Not Found**: If the job with the provided `job_id` is not found, the response will be:
101
+
102
+ ```json
103
+ {
104
+ "error": "Job not found",
105
+ "job_id": "e6d7f3c0-9c9f-4b8a-b7c3-f0e3c9f6b9d7"
106
+ }
107
+ ```
108
+
109
+ - **500 Internal Server Error**: If an unexpected error occurs while retrieving the job status, the response will be:
110
+
111
+ ```json
112
+ {
113
+ "error": "Failed to retrieve job status: <error_message>",
114
+ "code": 500
115
+ }
116
+ ```
117
+
118
+ ## 5. Error Handling
119
+
120
+ - **Missing or Invalid Parameters**: If the `job_id` parameter is missing or invalid, the request will be rejected with a 400 Bad Request error.
121
+ - **Job Not Found**: If the job with the provided `job_id` is not found, a 404 Not Found error will be returned.
122
+ - **Unexpected Errors**: Any unexpected errors that occur during the retrieval of the job status will result in a 500 Internal Server Error response.
123
+
124
+ The main application context (`app.py`) includes error handling for queue overflow situations, where a 429 Too Many Requests error is returned if the maximum queue length is reached.
125
+
126
+ ## 6. Usage Notes
127
+
128
+ - Ensure that you have a valid API key for authentication.
129
+ - The `job_id` parameter must be a valid UUID string representing an existing job.
130
+ - This endpoint does not perform any media processing; it only retrieves the status of a previously submitted job.
131
+
132
+ ## 7. Common Issues
133
+
134
+ - Providing an invalid or non-existent `job_id`.
135
+ - Attempting to retrieve the status of a job that has already been processed and removed from the system.
136
+
137
+ ## 8. Best Practices
138
+
139
+ - Use this endpoint to monitor the progress of long-running jobs or to check the status of completed jobs.
140
+ - Implement proper error handling in your client application to handle different error scenarios, such as job not found or unexpected errors.
141
+ - Consider rate-limiting or implementing a queue system on the client side to avoid overwhelming the API with too many requests.
docs/toolkit/jobs_status.md ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Get All Jobs Status
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/toolkit/jobs/status` endpoint is part of the Toolkit API and is used to retrieve the status of all jobs within a specified time range. This endpoint fits into the overall API structure by providing a way to monitor and manage the jobs that have been submitted to the system. It is a part of the `v1_toolkit_jobs_status_bp` blueprint, which is registered in the main `app.py` file.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/toolkit/jobs/status`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ - `since_seconds` (optional, number): The number of seconds to look back for jobs. If not provided, the default value is 600 seconds (10 minutes).
21
+
22
+ The JSON payload is completely optional. If no payload is provided or if the payload is empty, the endpoint will use the default value of 600 seconds.
23
+
24
+ ### Example Request
25
+
26
+ ```json
27
+ {
28
+ "since_seconds": 3600
29
+ }
30
+ ```
31
+
32
+ Or with no body:
33
+
34
+ ```bash
35
+ curl -X POST \
36
+ -H "x-api-key: YOUR_API_KEY" \
37
+ -H "Content-Type: application/json" \
38
+ http://your-api-url/v1/toolkit/jobs/status
39
+ ```
40
+
41
+ With body:
42
+
43
+ ```bash
44
+ curl -X POST \
45
+ -H "x-api-key: YOUR_API_KEY" \
46
+ -H "Content-Type: application/json" \
47
+ -d '{"since_seconds": 3600}' \
48
+ http://your-api-url/v1/toolkit/jobs/status
49
+ ```
50
+
51
+ ## 4. Response
52
+
53
+ ### Success Response
54
+
55
+ The response will be a JSON object containing the job statuses for all jobs within the specified time range. The response format follows the general response structure defined in `app.py`.
56
+
57
+ ```json
58
+ {
59
+ "code": 200,
60
+ "id": null,
61
+ "job_id": "job_id_value",
62
+ "response": {
63
+ "job_id_1": "job_status_1",
64
+ "job_id_2": "job_status_2",
65
+ ...
66
+ },
67
+ "message": "success",
68
+ "run_time": 0.123,
69
+ "queue_time": 0,
70
+ "total_time": 0.123,
71
+ "pid": 12345,
72
+ "queue_id": 1234567890,
73
+ "queue_length": 0,
74
+ "build_number": "1.0.0"
75
+ }
76
+ ```
77
+
78
+ ### Error Responses
79
+
80
+ - **404 Not Found**: If the jobs directory is not found.
81
+
82
+ ```json
83
+ {
84
+ "code": 404,
85
+ "id": null,
86
+ "job_id": "job_id_value",
87
+ "response": null,
88
+ "message": "Jobs directory not found",
89
+ "run_time": 0.123,
90
+ "queue_time": 0,
91
+ "total_time": 0.123,
92
+ "pid": 12345,
93
+ "queue_id": 1234567890,
94
+ "queue_length": 0,
95
+ "build_number": "1.0.0"
96
+ }
97
+ ```
98
+
99
+ - **500 Internal Server Error**: If an exception occurs while retrieving the job statuses.
100
+
101
+ ```json
102
+ {
103
+ "code": 500,
104
+ "id": null,
105
+ "job_id": "job_id_value",
106
+ "response": null,
107
+ "message": "Failed to retrieve job statuses: Error message",
108
+ "run_time": 0.123,
109
+ "queue_time": 0,
110
+ "total_time": 0.123,
111
+ "pid": 12345,
112
+ "queue_id": 1234567890,
113
+ "queue_length": 0,
114
+ "build_number": "1.0.0"
115
+ }
116
+ ```
117
+
118
+ ## 5. Error Handling
119
+
120
+ - Missing or invalid `x-api-key` header: The `authenticate` decorator will return a 401 Unauthorized error.
121
+ - Jobs directory not found: The endpoint will return a 404 Not Found error if the jobs directory is not found.
122
+ - Exception during job status retrieval: The endpoint will return a 500 Internal Server Error if an exception occurs while retrieving the job statuses.
123
+
124
+ The main `app.py` file includes error handling for queue overflow (429 Too Many Requests) and logging of job statuses (queued, running, done) using the `log_job_status` function.
125
+
126
+ ## 6. Usage Notes
127
+
128
+ - This endpoint is useful for monitoring the status of jobs submitted to the system, especially when dealing with long-running or queued jobs.
129
+ - The `since_seconds` parameter can be adjusted to retrieve job statuses within a specific time range, allowing for more targeted monitoring.
130
+
131
+ ## 7. Common Issues
132
+
133
+ - Providing an invalid `x-api-key` header will result in an authentication error.
134
+ - If the jobs directory is not found or an exception occurs during job status retrieval, the endpoint will return an error.
135
+
136
+ ## 8. Best Practices
137
+
138
+ - Always include the `x-api-key` header with a valid API key for authentication.
139
+ - Monitor the job statuses regularly to keep track of the progress and completion of submitted jobs.
140
+ - Adjust the `since_seconds` parameter based on your monitoring requirements to retrieve job statuses within a specific time range.
141
+ - Implement error handling and logging mechanisms to track and troubleshoot any issues that may arise.
docs/toolkit/test.md ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NCA Toolkit Test API Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/toolkit/test` endpoint is a part of the NCA Toolkit API and is designed to test the API setup. It creates a temporary file, uploads it to cloud storage, and then returns the upload URL. This endpoint serves as a simple test to ensure that the API is properly configured and can perform basic file operations and cloud storage interactions.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/toolkit/test`
10
+ **HTTP Method:** `GET`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ This endpoint does not require any request body parameters.
21
+
22
+ ### Example Request
23
+
24
+ ```bash
25
+ curl -X GET \
26
+ https://your-api-url.com/v1/toolkit/test \
27
+ -H 'x-api-key: your-api-key'
28
+ ```
29
+
30
+ ## 4. Response
31
+
32
+ ### Success Response
33
+
34
+ ```json
35
+ {
36
+ "endpoint": "/v1/toolkit/test",
37
+ "code": 200,
38
+ "id": null,
39
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
40
+ "response": "https://cloud-storage.com/success.txt",
41
+ "message": "success",
42
+ "pid": 12345,
43
+ "queue_id": 67890,
44
+ "run_time": 0.123,
45
+ "queue_time": 0.0,
46
+ "total_time": 0.123,
47
+ "queue_length": 0,
48
+ "build_number": "1.0.0"
49
+ }
50
+ ```
51
+
52
+ ### Error Responses
53
+
54
+ **Status Code: 401 Unauthorized**
55
+
56
+ ```json
57
+ {
58
+ "code": 401,
59
+ "message": "Unauthorized: Invalid or missing API key"
60
+ }
61
+ ```
62
+
63
+ **Status Code: 500 Internal Server Error**
64
+
65
+ ```json
66
+ {
67
+ "code": 500,
68
+ "message": "An error occurred while processing the request"
69
+ }
70
+ ```
71
+
72
+ ## 5. Error Handling
73
+
74
+ - **Missing or Invalid API Key (401 Unauthorized)**: If the `x-api-key` header is missing or invalid, the API will return a 401 Unauthorized error.
75
+ - **Internal Server Error (500)**: If an unexpected error occurs during the file creation, upload, or any other operation, the API will return a 500 Internal Server Error with the error message.
76
+
77
+ ## 6. Usage Notes
78
+
79
+ This endpoint is primarily used for testing purposes and does not require any specific input parameters. It can be called to verify that the API is set up correctly and can perform basic operations.
80
+
81
+ ## 7. Common Issues
82
+
83
+ - Incorrect or missing API key: Ensure that the `x-api-key` header is included with a valid API key.
84
+ - Temporary file creation or upload issues: If there are any issues with creating or uploading the temporary file, the API will return an error.
85
+
86
+ ## 8. Best Practices
87
+
88
+ - Use this endpoint during the initial setup and testing phase of the API integration to ensure that the API is configured correctly.
89
+ - Regularly test the API setup using this endpoint to catch any potential issues or configuration changes that may affect the API's functionality.
docs/video/caption_video.md ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Video Captioning Endpoint (v1)
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/video/caption` endpoint is part of the Video API and is responsible for adding captions to a video file. It accepts a video URL, caption text, and various styling options for the captions. The endpoint utilizes the `process_captioning_v1` service to generate a captioned video file, which is then uploaded to cloud storage, and the cloud URL is returned in the response.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL:** `/v1/video/caption`
10
+ **Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key`: Required. The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+
22
+ - `video_url` (string, required): The URL of the video file to be captioned.
23
+ - `captions` (string, optional): Can be one of the following:
24
+ - Raw caption text to be added to the video
25
+ - URL to an SRT subtitle file
26
+ - URL to an ASS subtitle file
27
+ - If not provided, the system will automatically generate captions by transcribing the audio from the video
28
+ - `settings` (object, optional): An object containing various styling options for the captions. See the schema below for available options.
29
+ - `replace` (array, optional): An array of objects with `find` and `replace` properties, specifying text replacements to be made in the captions.
30
+ - `webhook_url` (string, optional): A URL to receive a webhook notification when the captioning process is complete.
31
+ - `id` (string, optional): An identifier for the request.
32
+ - `language` (string, optional): The language code for the captions (e.g., "en", "fr"). Defaults to "auto".
33
+ - `exclude_time_ranges` (array, optional): List of time ranges to skip when adding captions. Each item must be an object with:
34
+ - `start`: (string, required) The start time of the excluded range, as a string timecode in `hh:mm:ss.ms` format (e.g., `00:01:23.456`).
35
+ - `end`: (string, required) The end time, as a string timecode in `hh:mm:ss.ms` format, which must be strictly greater than `start`.
36
+ If either value is not a valid timecode string, or if `end` is not greater than `start`, the request will return an error.
37
+
38
+ #### Settings Schema
39
+
40
+ ```json
41
+ {
42
+ "type": "object",
43
+ "properties": {
44
+ "line_color": {"type": "string"},
45
+ "word_color": {"type": "string"},
46
+ "outline_color": {"type": "string"},
47
+ "all_caps": {"type": "boolean"},
48
+ "max_words_per_line": {"type": "integer"},
49
+ "x": {"type": "integer"},
50
+ "y": {"type": "integer"},
51
+ "position": {
52
+ "type": "string",
53
+ "enum": [
54
+ "bottom_left", "bottom_center", "bottom_right",
55
+ "middle_left", "middle_center", "middle_right",
56
+ "top_left", "top_center", "top_right"
57
+ ]
58
+ },
59
+ "alignment": {
60
+ "type": "string",
61
+ "enum": ["left", "center", "right"]
62
+ },
63
+ "font_family": {"type": "string"},
64
+ "font_size": {"type": "integer"},
65
+ "bold": {"type": "boolean"},
66
+ "italic": {"type": "boolean"},
67
+ "underline": {"type": "boolean"},
68
+ "strikeout": {"type": "boolean"},
69
+ "style": {
70
+ "type": "string",
71
+ "enum": [
72
+ "classic", // Regular captioning with all text displayed at once
73
+ "karaoke", // Highlights words sequentially in a karaoke style
74
+ "highlight", // Shows full text but highlights the current word
75
+ "underline", // Shows full text but underlines the current word
76
+ "word_by_word" // Shows one word at a time
77
+ ]
78
+ },
79
+ "outline_width": {"type": "integer"},
80
+ "spacing": {"type": "integer"},
81
+ "angle": {"type": "integer"},
82
+ "shadow_offset": {"type": "integer"}
83
+ },
84
+ "additionalProperties": false
85
+ }
86
+ ```
87
+
88
+ ### Example Requests
89
+
90
+ #### Example 1: Basic Automatic Captioning
91
+ ```json
92
+ {
93
+ "video_url": "https://example.com/video.mp4"
94
+ }
95
+ ```
96
+ This minimal request will automatically transcribe the video and add white captions at the bottom center.
97
+
98
+ #### Example 2: Custom Text with Styling
99
+ ```json
100
+ {
101
+ "video_url": "https://example.com/video.mp4",
102
+ "captions": "This is a sample caption text.",
103
+ "settings": {
104
+ "style": "classic",
105
+ "line_color": "#FFFFFF",
106
+ "outline_color": "#000000",
107
+ "position": "bottom_center",
108
+ "alignment": "center",
109
+ "font_family": "Arial",
110
+ "font_size": 24,
111
+ "bold": true
112
+ }
113
+ }
114
+ ```
115
+
116
+ #### Example 3: Karaoke-Style Captions with Advanced Options
117
+ ```json
118
+ {
119
+ "video_url": "https://example.com/video.mp4",
120
+ "settings": {
121
+ "line_color": "#FFFFFF",
122
+ "word_color": "#FFFF00",
123
+ "outline_color": "#000000",
124
+ "all_caps": false,
125
+ "max_words_per_line": 10,
126
+ "position": "bottom_center",
127
+ "alignment": "center",
128
+ "font_family": "Arial",
129
+ "font_size": 24,
130
+ "bold": false,
131
+ "italic": false,
132
+ "style": "karaoke",
133
+ "outline_width": 2,
134
+ "shadow_offset": 2
135
+ },
136
+ "replace": [
137
+ {
138
+ "find": "um",
139
+ "replace": ""
140
+ },
141
+ {
142
+ "find": "like",
143
+ "replace": ""
144
+ }
145
+ ],
146
+ "webhook_url": "https://example.com/webhook",
147
+ "id": "request-123",
148
+ "language": "en"
149
+ }
150
+ ```
151
+
152
+ #### Example 4: Using an External Subtitle File
153
+ ```json
154
+ {
155
+ "video_url": "https://example.com/video.mp4",
156
+ "captions": "https://example.com/subtitles.srt",
157
+ "settings": {
158
+ "line_color": "#FFFFFF",
159
+ "outline_color": "#000000",
160
+ "position": "bottom_center",
161
+ "font_family": "Arial",
162
+ "font_size": 24
163
+ }
164
+ }
165
+ ```
166
+
167
+ #### Example 5: Excluding Time Ranges from Captioning
168
+ ```json
169
+ {
170
+ "video_url": "https://example.com/video.mp4",
171
+ "settings": {
172
+ "style": "classic",
173
+ "line_color": "#FFFFFF",
174
+ "outline_color": "#000000",
175
+ "position": "bottom_center",
176
+ "font_family": "Arial",
177
+ "font_size": 24
178
+ },
179
+ "exclude_time_ranges": [
180
+ { "start": "00:00:10.000", "end": "00:00:20.000" },
181
+ { "start": "00:00:30.000", "end": "00:00:40.000" }
182
+ ]
183
+ }
184
+ ```
185
+
186
+ ```bash
187
+ curl -X POST \
188
+ -H "x-api-key: YOUR_API_KEY" \
189
+ -H "Content-Type: application/json" \
190
+ -d '{
191
+ "video_url": "https://example.com/video.mp4",
192
+ "settings": {
193
+ "line_color": "#FFFFFF",
194
+ "word_color": "#FFFF00",
195
+ "outline_color": "#000000",
196
+ "all_caps": false,
197
+ "max_words_per_line": 10,
198
+ "position": "bottom_center",
199
+ "alignment": "center",
200
+ "font_family": "Arial",
201
+ "font_size": 24,
202
+ "style": "karaoke",
203
+ "outline_width": 2
204
+ },
205
+ "replace": [
206
+ {
207
+ "find": "um",
208
+ "replace": ""
209
+ }
210
+ ],
211
+ "id": "custom-request-id"
212
+ }' \
213
+ https://your-api-endpoint.com/v1/video/caption
214
+ ```
215
+
216
+ ## 4. Response
217
+
218
+ ### Success Response
219
+
220
+ The response will be a JSON object with the following properties:
221
+
222
+ - `code` (integer): The HTTP status code (200 for success).
223
+ - `id` (string): The request identifier, if provided in the request.
224
+ - `job_id` (string): A unique identifier for the job.
225
+ - `response` (string): The cloud URL of the captioned video file.
226
+ - `message` (string): A success message.
227
+ - `pid` (integer): The process ID of the worker that processed the request.
228
+ - `queue_id` (integer): The ID of the queue used for processing the request.
229
+ - `run_time` (float): The time taken to process the request (in seconds).
230
+ - `queue_time` (float): The time the request spent in the queue (in seconds).
231
+ - `total_time` (float): The total time taken for the request (in seconds).
232
+ - `queue_length` (integer): The current length of the processing queue.
233
+ - `build_number` (string): The build number of the application.
234
+
235
+ Example:
236
+
237
+ ```json
238
+ {
239
+ "code": 200,
240
+ "id": "request-123",
241
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
242
+ "response": "https://cloud.example.com/captioned-video.mp4",
243
+ "message": "success",
244
+ "pid": 12345,
245
+ "queue_id": 140682639937472,
246
+ "run_time": 5.234,
247
+ "queue_time": 0.012,
248
+ "total_time": 5.246,
249
+ "queue_length": 0,
250
+ "build_number": "1.0.0"
251
+ }
252
+ ```
253
+
254
+ ### Error Responses
255
+
256
+ #### Missing or Invalid Parameters
257
+
258
+ **Status Code:** 400 Bad Request
259
+
260
+ ```json
261
+ {
262
+ "code": 400,
263
+ "id": "request-123",
264
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
265
+ "message": "Missing or invalid parameters",
266
+ "pid": 12345,
267
+ "queue_id": 140682639937472,
268
+ "queue_length": 0,
269
+ "build_number": "1.0.0"
270
+ }
271
+ ```
272
+
273
+ #### Font Error
274
+
275
+ **Status Code:** 400 Bad Request
276
+
277
+ ```json
278
+ {
279
+ "code": 400,
280
+ "error": "The requested font 'InvalidFont' is not available. Please choose from the available fonts.",
281
+ "available_fonts": ["Arial", "Times New Roman", "Courier New", ...],
282
+ "pid": 12345,
283
+ "queue_id": 140682639937472,
284
+ "queue_length": 0,
285
+ "build_number": "1.0.0"
286
+ }
287
+ ```
288
+
289
+ #### Internal Server Error
290
+
291
+ **Status Code:** 500 Internal Server Error
292
+
293
+ ```json
294
+ {
295
+ "code": 500,
296
+ "id": "request-123",
297
+ "job_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
298
+ "error": "An unexpected error occurred during the captioning process.",
299
+ "pid": 12345,
300
+ "queue_id": 140682639937472,
301
+ "queue_length": 0,
302
+ "build_number": "1.0.0"
303
+ }
304
+ ```
305
+
306
+ ## 5. Error Handling
307
+
308
+ The endpoint handles the following common errors:
309
+
310
+ - **Missing or Invalid Parameters**: If any required parameters are missing or invalid, a 400 Bad Request error is returned with a descriptive error message.
311
+ - **Font Error**: If the requested font is not available, a 400 Bad Request error is returned with a list of available fonts.
312
+ - **Internal Server Error**: If an unexpected error occurs during the captioning process, a 500 Internal Server Error is returned with an error message.
313
+
314
+ Additionally, the main application context (`app.py`) includes error handling for queue overload. If the maximum queue length (`MAX_QUEUE_LENGTH`) is set and the queue size reaches that limit, a 429 Too Many Requests error is returned with a descriptive message.
315
+
316
+ ## 6. Usage Notes
317
+
318
+ - The `video_url` parameter must be a valid URL pointing to a video file (MP4, MOV, etc.).
319
+ - The `captions` parameter is optional and can be used in multiple ways:
320
+ - If not provided, the endpoint will automatically transcribe the audio and generate captions
321
+ - If provided as plain text, the text will be used as captions for the entire video
322
+ - If provided as a URL to an SRT or ASS subtitle file, the system will use that file for captioning
323
+ - For SRT files, only 'classic' style is supported
324
+ - For ASS files, the original styling will be preserved
325
+ - The `settings` parameter allows for customization of the caption appearance and behavior:
326
+ - `style` determines how captions are displayed, with options including:
327
+ - `classic`: Regular captioning with all text displayed at once
328
+ - `karaoke`: Highlights words sequentially in a karaoke style as they're spoken
329
+ - `highlight`: Shows the full caption text but highlights each word as it's spoken
330
+ - `underline`: Shows the full caption text but underlines each word as it's spoken
331
+ - `word_by_word`: Shows only one word at a time
332
+ - `position` can be used to place captions in one of nine positions on the screen
333
+ - `alignment` determines text alignment within the position (left, center, right)
334
+ - `font_family` can be any available system font
335
+ - Color options can be set using hex codes (e.g., "#FFFFFF" for white)
336
+ - The `replace` parameter can be used to perform text replacements in the captions (useful for correcting words or censoring content).
337
+ - The `webhook_url` parameter is optional and can be used to receive a notification when the captioning process is complete.
338
+ - The `id` parameter is optional and can be used to identify the request in webhook responses.
339
+ - The `language` parameter is optional and can be used to specify the language of the captions for transcription. If not provided, the language will be automatically detected.
340
+ - The `exclude_time_ranges` parameter can be used to specify time ranges to be excluded from captioning.
341
+
342
+ ## 7. Common Issues
343
+
344
+ - Providing an invalid or inaccessible `video_url`.
345
+ - Requesting an unavailable font in the `settings` object.
346
+ - Exceeding the maximum queue length, resulting in a 429 Too Many Requests error.
347
+
348
+ ## 8. Best Practices
349
+
350
+ - Validate the `video_url` parameter before sending the request to ensure it points to a valid and accessible video file.
351
+ - Use the `webhook_url` parameter to receive notifications about the captioning process, rather than polling the API for updates.
352
+ - Provide descriptive and meaningful `id` values to easily identify requests in logs and responses.
353
+ - Use the `replace` parameter judiciously to avoid unintended text replacements in the captions.
354
+ - Consider caching the captioned video files for frequently requested videos to improve performance and reduce processing time.
docs/video/concatenate.md ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Video Concatenation Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/video/concatenate` endpoint is a part of the Video API and is responsible for combining multiple video files into a single video file. This endpoint fits into the overall API structure as a part of the version 1 (v1) routes, specifically under the `/v1/video` namespace.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/video/concatenate`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+
22
+ - `video_urls` (required, array of objects): An array of video URLs to be concatenated. Each object in the array must have a `video_url` property (string, URI format) containing the URL of the video file.
23
+ - `webhook_url` (optional, string, URI format): The URL to which the response should be sent as a webhook.
24
+ - `id` (optional, string): An identifier for the request.
25
+
26
+ The `validate_payload` decorator in the routes file enforces the following JSON schema for the request body:
27
+
28
+ ```json
29
+ {
30
+ "type": "object",
31
+ "properties": {
32
+ "video_urls": {
33
+ "type": "array",
34
+ "items": {
35
+ "type": "object",
36
+ "properties": {
37
+ "video_url": {"type": "string", "format": "uri"}
38
+ },
39
+ "required": ["video_url"]
40
+ },
41
+ "minItems": 1
42
+ },
43
+ "webhook_url": {"type": "string", "format": "uri"},
44
+ "id": {"type": "string"}
45
+ },
46
+ "required": ["video_urls"],
47
+ "additionalProperties": False
48
+ }
49
+ ```
50
+
51
+ ### Example Request
52
+
53
+ ```json
54
+ {
55
+ "video_urls": [
56
+ {"video_url": "https://example.com/video1.mp4"},
57
+ {"video_url": "https://example.com/video2.mp4"},
58
+ {"video_url": "https://example.com/video3.mp4"}
59
+ ],
60
+ "webhook_url": "https://example.com/webhook",
61
+ "id": "request-123"
62
+ }
63
+ ```
64
+
65
+ ```bash
66
+ curl -X POST \
67
+ -H "x-api-key: YOUR_API_KEY" \
68
+ -H "Content-Type: application/json" \
69
+ -d '{
70
+ "video_urls": [
71
+ {"video_url": "https://example.com/video1.mp4"},
72
+ {"video_url": "https://example.com/video2.mp4"},
73
+ {"video_url": "https://example.com/video3.mp4"}
74
+ ],
75
+ "webhook_url": "https://example.com/webhook",
76
+ "id": "request-123"
77
+ }' \
78
+ https://your-api-endpoint.com/v1/video/concatenate
79
+ ```
80
+
81
+ ## 4. Response
82
+
83
+ ### Success Response
84
+
85
+ The success response follows the general response format defined in the `app.py` file. Here's an example:
86
+
87
+ ```json
88
+ {
89
+ "endpoint": "/v1/video/concatenate",
90
+ "code": 200,
91
+ "id": "request-123",
92
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
93
+ "response": "https://cloud-storage.example.com/combined-video.mp4",
94
+ "message": "success",
95
+ "pid": 12345,
96
+ "queue_id": 6789,
97
+ "run_time": 10.234,
98
+ "queue_time": 2.345,
99
+ "total_time": 12.579,
100
+ "queue_length": 0,
101
+ "build_number": "1.0.0"
102
+ }
103
+ ```
104
+
105
+ The `response` field contains the URL of the combined video file uploaded to cloud storage.
106
+
107
+ ### Error Responses
108
+
109
+ - **400 Bad Request**: Returned when the request body is missing or invalid.
110
+
111
+ ```json
112
+ {
113
+ "code": 400,
114
+ "message": "Invalid request payload"
115
+ }
116
+ ```
117
+
118
+ - **401 Unauthorized**: Returned when the `x-api-key` header is missing or invalid.
119
+
120
+ ```json
121
+ {
122
+ "code": 401,
123
+ "message": "Unauthorized"
124
+ }
125
+ ```
126
+
127
+ - **429 Too Many Requests**: Returned when the maximum queue length is reached.
128
+
129
+ ```json
130
+ {
131
+ "code": 429,
132
+ "id": "request-123",
133
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
134
+ "message": "MAX_QUEUE_LENGTH (100) reached",
135
+ "pid": 12345,
136
+ "queue_id": 6789,
137
+ "queue_length": 100,
138
+ "build_number": "1.0.0"
139
+ }
140
+ ```
141
+
142
+ - **500 Internal Server Error**: Returned when an unexpected error occurs during the video concatenation process.
143
+
144
+ ```json
145
+ {
146
+ "code": 500,
147
+ "message": "An error occurred during video concatenation"
148
+ }
149
+ ```
150
+
151
+ ## 5. Error Handling
152
+
153
+ The endpoint handles the following common errors:
154
+
155
+ - **Missing or invalid request body**: If the request body is missing or does not conform to the expected JSON schema, a 400 Bad Request error is returned.
156
+ - **Missing or invalid API key**: If the `x-api-key` header is missing or invalid, a 401 Unauthorized error is returned.
157
+ - **Queue length exceeded**: If the maximum queue length is reached (determined by the `MAX_QUEUE_LENGTH` environment variable), a 429 Too Many Requests error is returned.
158
+ - **Unexpected errors during video concatenation**: If an unexpected error occurs during the video concatenation process, a 500 Internal Server Error is returned with the error message.
159
+
160
+ The main application context (`app.py`) also includes error handling for the task queue. If the queue length exceeds the `MAX_QUEUE_LENGTH` limit, the request is rejected with a 429 Too Many Requests error.
161
+
162
+ ## 6. Usage Notes
163
+
164
+ - The video files to be concatenated must be accessible via the provided URLs.
165
+ - The order of the video files in the `video_urls` array determines the order in which they will be concatenated.
166
+ - If the `webhook_url` parameter is provided, the response will be sent as a webhook to the specified URL.
167
+ - The `id` parameter can be used to identify the request in the response.
168
+
169
+ ## 7. Common Issues
170
+
171
+ - Providing invalid or inaccessible video URLs.
172
+ - Exceeding the maximum queue length, which can lead to requests being rejected with a 429 Too Many Requests error.
173
+ - Encountering unexpected errors during the video concatenation process, which can result in a 500 Internal Server Error.
174
+
175
+ ## 8. Best Practices
176
+
177
+ - Validate the video URLs before sending the request to ensure they are accessible and in the correct format.
178
+ - Monitor the queue length and adjust the `MAX_QUEUE_LENGTH` value accordingly to prevent requests from being rejected due to a full queue.
179
+ - Implement retry mechanisms for handling temporary errors or failures during the video concatenation process.
180
+ - Provide meaningful and descriptive `id` values to easily identify requests in the response.
docs/video/cut.md ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Video Cut Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/video/cut` endpoint is part of the Video API and allows users to cut specified segments from a video file with optional encoding settings. This endpoint fits into the overall API structure as a part of the version 1 (`v1`) routes, specifically under the `video` category.
6
+
7
+ ## 2. Endpoint
8
+
9
+ ```
10
+ POST /v1/video/cut
11
+ ```
12
+
13
+ ## 3. Request
14
+
15
+ ### Headers
16
+
17
+ - `x-api-key` (required): The API key for authentication.
18
+
19
+ ### Body Parameters
20
+
21
+ The request body must be a JSON object with the following properties:
22
+
23
+ - `video_url` (required, string): The URL of the video file to be cut.
24
+ - `cuts` (required, array of objects): An array of cut segments, where each object has the following properties:
25
+ - `start` (required, string): The start time of the cut segment in the format `hh:mm:ss.ms`.
26
+ - `end` (required, string): The end time of the cut segment in the format `hh:mm:ss.ms`.
27
+ - `video_codec` (optional, string): The video codec to use for encoding the output video. Default is `libx264`.
28
+ - `video_preset` (optional, string): The video preset to use for encoding the output video. Default is `medium`.
29
+ - `video_crf` (optional, number): The Constant Rate Factor (CRF) value for video encoding. Must be between 0 and 51. Default is 23.
30
+ - `audio_codec` (optional, string): The audio codec to use for encoding the output video. Default is `aac`.
31
+ - `audio_bitrate` (optional, string): The audio bitrate to use for encoding the output video. Default is `128k`.
32
+ - `webhook_url` (optional, string): The URL to receive a webhook notification when the job is completed.
33
+ - `id` (optional, string): A unique identifier for the request.
34
+
35
+ ### Example Request
36
+
37
+ ```json
38
+ {
39
+ "video_url": "https://example.com/video.mp4",
40
+ "cuts": [
41
+ {
42
+ "start": "00:00:10.000",
43
+ "end": "00:00:20.000"
44
+ },
45
+ {
46
+ "start": "00:00:30.000",
47
+ "end": "00:00:40.000"
48
+ }
49
+ ],
50
+ "video_codec": "libx264",
51
+ "video_preset": "medium",
52
+ "video_crf": 23,
53
+ "audio_codec": "aac",
54
+ "audio_bitrate": "128k",
55
+ "webhook_url": "https://example.com/webhook",
56
+ "id": "unique-request-id"
57
+ }
58
+ ```
59
+
60
+ ```bash
61
+ curl -X POST \
62
+ https://api.example.com/v1/video/cut \
63
+ -H 'x-api-key: YOUR_API_KEY' \
64
+ -H 'Content-Type: application/json' \
65
+ -d '{
66
+ "video_url": "https://example.com/video.mp4",
67
+ "cuts": [
68
+ {
69
+ "start": "00:00:10.000",
70
+ "end": "00:00:20.000"
71
+ },
72
+ {
73
+ "start": "00:00:30.000",
74
+ "end": "00:00:40.000"
75
+ }
76
+ ],
77
+ "video_codec": "libx264",
78
+ "video_preset": "medium",
79
+ "video_crf": 23,
80
+ "audio_codec": "aac",
81
+ "audio_bitrate": "128k",
82
+ "webhook_url": "https://example.com/webhook",
83
+ "id": "unique-request-id"
84
+ }'
85
+ ```
86
+
87
+ ## 4. Response
88
+
89
+ ### Success Response
90
+
91
+ The response follows the general response format defined in the main application context (`app.py`). Here's an example of a successful response:
92
+
93
+ ```json
94
+ {
95
+ "endpoint": "/v1/video/cut",
96
+ "code": 200,
97
+ "id": "unique-request-id",
98
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
99
+ "response": "https://example.com/processed-video.mp4",
100
+ "message": "success",
101
+ "pid": 12345,
102
+ "queue_id": 6789,
103
+ "run_time": 5.234,
104
+ "queue_time": 0.123,
105
+ "total_time": 5.357,
106
+ "queue_length": 0,
107
+ "build_number": "1.0.0"
108
+ }
109
+ ```
110
+
111
+ The `response` field contains the URL of the processed video file.
112
+
113
+ ### Error Responses
114
+
115
+ - **400 Bad Request**
116
+
117
+ ```json
118
+ {
119
+ "code": 400,
120
+ "message": "Invalid request payload"
121
+ }
122
+ ```
123
+
124
+ This error occurs when the request payload is missing required fields or contains invalid data.
125
+
126
+ - **401 Unauthorized**
127
+
128
+ ```json
129
+ {
130
+ "code": 401,
131
+ "message": "Invalid API key"
132
+ }
133
+ ```
134
+
135
+ This error occurs when the provided `x-api-key` header is missing or invalid.
136
+
137
+ - **429 Too Many Requests**
138
+
139
+ ```json
140
+ {
141
+ "code": 429,
142
+ "id": "unique-request-id",
143
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
144
+ "message": "MAX_QUEUE_LENGTH (100) reached",
145
+ "pid": 12345,
146
+ "queue_id": 6789,
147
+ "queue_length": 100,
148
+ "build_number": "1.0.0"
149
+ }
150
+ ```
151
+
152
+ This error occurs when the maximum queue length has been reached, and the request cannot be processed immediately.
153
+
154
+ - **500 Internal Server Error**
155
+
156
+ ```json
157
+ {
158
+ "code": 500,
159
+ "message": "An error occurred during video processing"
160
+ }
161
+ ```
162
+
163
+ This error occurs when an unexpected error occurs during the video processing or encoding.
164
+
165
+ ## 5. Error Handling
166
+
167
+ The endpoint handles the following common errors:
168
+
169
+ - **Missing or invalid request parameters**: If any required parameters are missing or invalid, the endpoint returns a 400 Bad Request error with an appropriate error message.
170
+ - **Invalid API key**: If the provided `x-api-key` header is missing or invalid, the endpoint returns a 401 Unauthorized error.
171
+ - **Queue limit reached**: If the maximum queue length has been reached, the endpoint returns a 429 Too Many Requests error with the current queue length and the maximum queue length.
172
+ - **Unexpected errors during video processing**: If an unexpected error occurs during the video processing or encoding, the endpoint returns a 500 Internal Server Error with a generic error message.
173
+
174
+ The main application context (`app.py`) also includes error handling for the queue system and webhook notifications.
175
+
176
+ ## 6. Usage Notes
177
+
178
+ - The `video_url` parameter must be a valid URL that points to a video file accessible by the server.
179
+ - The `cuts` parameter must be an array of objects, where each object represents a cut segment with a start and end time in the format `hh:mm:ss.ms`.
180
+ - The optional encoding parameters (`video_codec`, `video_preset`, `video_crf`, `audio_codec`, `audio_bitrate`) allow you to customize the encoding settings for the output video file.
181
+ - If the `webhook_url` parameter is provided, the server will send a webhook notification to the specified URL when the job is completed.
182
+ - The `id` parameter can be used to associate the request with a unique identifier for tracking purposes.
183
+
184
+ ## 7. Common Issues
185
+
186
+ - Providing an invalid or inaccessible `video_url`.
187
+ - Specifying overlapping or invalid cut segments in the `cuts` parameter.
188
+ - Providing invalid encoding settings that are not supported by the server.
189
+ - Reaching the maximum queue length, which can cause requests to be rejected with a 429 Too Many Requests error.
190
+
191
+ ## 8. Best Practices
192
+
193
+ - Validate the `video_url` parameter before sending the request to ensure it points to a valid and accessible video file.
194
+ - Ensure that the cut segments in the `cuts` parameter are correctly formatted and do not overlap or exceed the duration of the video.
195
+ - Use the optional encoding parameters judiciously, as they can impact the processing time and output video quality.
196
+ - Implement retry mechanisms for handling 429 Too Many Requests errors, as the queue length may fluctuate over time.
197
+ - Monitor the webhook notifications or poll the server for job status updates to track the progress of long-running jobs.
docs/video/split.md ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Video Split Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/video/split` endpoint is part of the Video API and is used to split a video file into multiple segments based on specified start and end times. This endpoint fits into the overall API structure as a part of the version 1 (`v1`) routes, specifically under the `video` category.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/video/split`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ The request body must be a JSON object with the following properties:
21
+
22
+ - `video_url` (required, string): The URL of the video file to be split.
23
+ - `splits` (required, array of objects): An array of objects specifying the start and end times for each split. Each object must have the following properties:
24
+ - `start` (required, string): The start time of the split in the format `hh:mm:ss.ms`.
25
+ - `end` (required, string): The end time of the split in the format `hh:mm:ss.ms`.
26
+ - `video_codec` (optional, string): The video codec to use for encoding the split videos. Default is `libx264`.
27
+ - `video_preset` (optional, string): The video preset to use for encoding the split videos. Default is `medium`.
28
+ - `video_crf` (optional, number): The Constant Rate Factor (CRF) value for video encoding. Must be between 0 and 51. Default is 23.
29
+ - `audio_codec` (optional, string): The audio codec to use for encoding the split videos. Default is `aac`.
30
+ - `audio_bitrate` (optional, string): The audio bitrate to use for encoding the split videos. Default is `128k`.
31
+ - `webhook_url` (optional, string): The URL to receive a webhook notification when the split operation is complete.
32
+ - `id` (optional, string): A unique identifier for the request.
33
+
34
+ ### Example Request
35
+
36
+ ```json
37
+ {
38
+ "video_url": "https://example.com/video.mp4",
39
+ "splits": [
40
+ {
41
+ "start": "00:00:10.000",
42
+ "end": "00:00:20.000"
43
+ },
44
+ {
45
+ "start": "00:00:30.000",
46
+ "end": "00:00:40.000"
47
+ }
48
+ ],
49
+ "video_codec": "libx264",
50
+ "video_preset": "medium",
51
+ "video_crf": 23,
52
+ "audio_codec": "aac",
53
+ "audio_bitrate": "128k",
54
+ "webhook_url": "https://example.com/webhook",
55
+ "id": "unique-request-id"
56
+ }
57
+ ```
58
+
59
+ ```bash
60
+ curl -X POST \
61
+ https://api.example.com/v1/video/split \
62
+ -H 'x-api-key: YOUR_API_KEY' \
63
+ -H 'Content-Type: application/json' \
64
+ -d '{
65
+ "video_url": "https://example.com/video.mp4",
66
+ "splits": [
67
+ {
68
+ "start": "00:00:10.000",
69
+ "end": "00:00:20.000"
70
+ },
71
+ {
72
+ "start": "00:00:30.000",
73
+ "end": "00:00:40.000"
74
+ }
75
+ ],
76
+ "video_codec": "libx264",
77
+ "video_preset": "medium",
78
+ "video_crf": 23,
79
+ "audio_codec": "aac",
80
+ "audio_bitrate": "128k",
81
+ "webhook_url": "https://example.com/webhook",
82
+ "id": "unique-request-id"
83
+ }'
84
+ ```
85
+
86
+ ## 4. Response
87
+
88
+ ### Success Response
89
+
90
+ The success response follows the general response format specified in `app.py`. Here's an example:
91
+
92
+ ```json
93
+ {
94
+ "endpoint": "/v1/video/split",
95
+ "code": 200,
96
+ "id": "unique-request-id",
97
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
98
+ "response": [
99
+ {
100
+ "file_url": "https://example.com/split-1.mp4"
101
+ },
102
+ {
103
+ "file_url": "https://example.com/split-2.mp4"
104
+ }
105
+ ],
106
+ "message": "success",
107
+ "pid": 12345,
108
+ "queue_id": 6789,
109
+ "run_time": 5.234,
110
+ "queue_time": 0.123,
111
+ "total_time": 5.357,
112
+ "queue_length": 0,
113
+ "build_number": "1.0.0"
114
+ }
115
+ ```
116
+
117
+ The `response` field contains an array of objects, each representing a split video file. Each object has a `file_url` property containing the URL of the split video file.
118
+
119
+ ### Error Responses
120
+
121
+ - **400 Bad Request**: Returned when the request payload is missing or invalid.
122
+ - **401 Unauthorized**: Returned when the `x-api-key` header is missing or invalid.
123
+ - **429 Too Many Requests**: Returned when the maximum queue length has been reached.
124
+ - **500 Internal Server Error**: Returned when an unexpected error occurs during the video split process.
125
+
126
+ Example error response:
127
+
128
+ ```json
129
+ {
130
+ "code": 400,
131
+ "id": "unique-request-id",
132
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
133
+ "message": "Invalid request payload: 'splits' is a required property",
134
+ "pid": 12345,
135
+ "queue_id": 6789,
136
+ "queue_length": 2,
137
+ "build_number": "1.0.0"
138
+ }
139
+ ```
140
+
141
+ ## 5. Error Handling
142
+
143
+ The endpoint handles the following common errors:
144
+
145
+ - Missing or invalid request parameters: Returns a 400 Bad Request error with a descriptive error message.
146
+ - Authentication failure: Returns a 401 Unauthorized error if the `x-api-key` header is missing or invalid.
147
+ - Queue length exceeded: Returns a 429 Too Many Requests error if the maximum queue length has been reached.
148
+ - Unexpected exceptions: Returns a 500 Internal Server Error with the exception message.
149
+
150
+ The main application context (`app.py`) also includes error handling for queue length limits and webhook notifications.
151
+
152
+ ## 6. Usage Notes
153
+
154
+ - The `video_url` parameter must be a valid URL pointing to a video file.
155
+ - The `splits` array must contain at least one object specifying the start and end times for a split.
156
+ - The start and end times must be in the format `hh:mm:ss.ms` (hours:minutes:seconds.milliseconds).
157
+ - The `video_codec`, `video_preset`, `video_crf`, `audio_codec`, and `audio_bitrate` parameters are optional and can be used to customize the encoding settings for the split videos.
158
+ - If the `webhook_url` parameter is provided, a webhook notification will be sent to the specified URL when the split operation is complete.
159
+ - The `id` parameter is optional and can be used to uniquely identify the request.
160
+
161
+ ## 7. Common Issues
162
+
163
+ - Providing an invalid or inaccessible `video_url`.
164
+ - Specifying overlapping or invalid start and end times in the `splits` array.
165
+ - Exceeding the maximum queue length, which can result in a 429 Too Many Requests error.
166
+
167
+ ## 8. Best Practices
168
+
169
+ - Validate the `video_url` parameter before sending the request to ensure it points to a valid video file.
170
+ - Ensure that the start and end times in the `splits` array are correctly formatted and do not overlap.
171
+ - Consider using the `webhook_url` parameter to receive notifications about the completion of the split operation, especially for long-running or asynchronous requests.
172
+ - Implement retry mechanisms and error handling in your client application to handle potential errors and failures.
173
+ - Monitor the queue length and adjust the `MAX_QUEUE_LENGTH` environment variable as needed to prevent excessive queuing and potential timeouts.
docs/video/thumbnail.md ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Video Thumbnail Generation API
2
+
3
+ ## Overview
4
+
5
+ The `/v1/video/thumbnail` endpoint allows users to extract a thumbnail image from a specific timestamp in a video. This endpoint is part of the video processing capabilities of the API, which includes other features like video concatenation and captioning. The endpoint processes the request asynchronously using a queue system, uploads the generated thumbnail to cloud storage, and returns the URL of the uploaded image.
6
+
7
+ ## Endpoint
8
+
9
+ - **URL**: `/v1/video/thumbnail`
10
+ - **Method**: `POST`
11
+
12
+ ## Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key`: Required. Your API authentication key.
17
+
18
+ ### Body Parameters
19
+
20
+ | Parameter | Type | Required | Description |
21
+ |-----------|------|----------|-------------|
22
+ | `video_url` | string (URI format) | Yes | URL of the video from which to extract the thumbnail |
23
+ | `second` | number (minimum: 0) | No | Timestamp in seconds at which to extract the thumbnail (defaults to 0) |
24
+ | `webhook_url` | string (URI format) | No | URL to receive the processing result asynchronously |
25
+ | `id` | string | No | Custom identifier for tracking the request |
26
+
27
+ ### Example Request
28
+
29
+ ```json
30
+ {
31
+ "video_url": "https://example.com/video.mp4",
32
+ "second": 30,
33
+ "webhook_url": "https://your-service.com/webhook",
34
+ "id": "custom-request-123"
35
+ }
36
+ ```
37
+
38
+ ### Example cURL Command
39
+
40
+ ```bash
41
+ curl -X POST \
42
+ https://api.example.com/v1/video/thumbnail \
43
+ -H 'Content-Type: application/json' \
44
+ -H 'x-api-key: your-api-key' \
45
+ -d '{
46
+ "video_url": "https://example.com/video.mp4",
47
+ "second": 30,
48
+ "webhook_url": "https://your-service.com/webhook",
49
+ "id": "custom-request-123"
50
+ }'
51
+ ```
52
+
53
+ ## Response
54
+
55
+ ### Immediate Response (Status Code: 202)
56
+
57
+ When a webhook URL is provided, the API immediately returns a 202 Accepted response and processes the request asynchronously:
58
+
59
+ ```json
60
+ {
61
+ "code": 202,
62
+ "id": "custom-request-123",
63
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
64
+ "message": "processing",
65
+ "pid": 12345,
66
+ "queue_id": 67890,
67
+ "max_queue_length": "unlimited",
68
+ "queue_length": 1,
69
+ "build_number": "1.0.0"
70
+ }
71
+ ```
72
+
73
+ ### Success Response (Status Code: 200)
74
+
75
+ When no webhook URL is provided or when the webhook is called after processing:
76
+
77
+ ```json
78
+ {
79
+ "code": 200,
80
+ "id": "custom-request-123",
81
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
82
+ "response": "https://storage.example.com/thumbnails/video-thumbnail-123.jpg",
83
+ "message": "success",
84
+ "run_time": 1.234,
85
+ "queue_time": 0.567,
86
+ "total_time": 1.801,
87
+ "pid": 12345,
88
+ "queue_id": 67890,
89
+ "queue_length": 0,
90
+ "build_number": "1.0.0"
91
+ }
92
+ ```
93
+
94
+ ### Error Responses
95
+
96
+ #### Invalid Request (Status Code: 400)
97
+
98
+ ```json
99
+ {
100
+ "code": 400,
101
+ "message": "Invalid request: 'video_url' is a required property",
102
+ "job_id": "550e8400-e29b-41d4-a716-446655440000"
103
+ }
104
+ ```
105
+
106
+ #### Queue Full (Status Code: 429)
107
+
108
+ ```json
109
+ {
110
+ "code": 429,
111
+ "id": "custom-request-123",
112
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
113
+ "message": "MAX_QUEUE_LENGTH (100) reached",
114
+ "pid": 12345,
115
+ "queue_id": 67890,
116
+ "queue_length": 100,
117
+ "build_number": "1.0.0"
118
+ }
119
+ ```
120
+
121
+ #### Server Error (Status Code: 500)
122
+
123
+ ```json
124
+ {
125
+ "code": 500,
126
+ "id": "custom-request-123",
127
+ "job_id": "550e8400-e29b-41d4-a716-446655440000",
128
+ "message": "Failed to download video from provided URL",
129
+ "pid": 12345,
130
+ "queue_id": 67890,
131
+ "queue_length": 0,
132
+ "build_number": "1.0.0"
133
+ }
134
+ ```
135
+
136
+ ## Error Handling
137
+
138
+ The endpoint handles various error scenarios:
139
+
140
+ - **Missing Required Parameters**: Returns a 400 error if `video_url` is missing.
141
+ - **Invalid Parameter Format**: Returns a 400 error if parameters don't match the expected format (e.g., invalid URLs).
142
+ - **Queue Capacity**: Returns a 429 error if the processing queue is full.
143
+ - **Processing Errors**: Returns a 500 error if there are issues during thumbnail extraction or upload.
144
+
145
+ ## Usage Notes
146
+
147
+ 1. **Asynchronous Processing**: For long-running operations, provide a `webhook_url` to receive the result asynchronously.
148
+ 2. **Timestamp Selection**: Choose an appropriate `second` value to capture a meaningful frame from the video.
149
+ 3. **Request Tracking**: Use the `id` parameter to track your requests across your systems.
150
+ 4. **Queue Management**: The API uses a queue system with configurable maximum length (set by the `MAX_QUEUE_LENGTH` environment variable).
151
+
152
+ ## Common Issues
153
+
154
+ 1. **Inaccessible Video URLs**: Ensure the video URL is publicly accessible or has proper authentication.
155
+ 2. **Invalid Timestamp**: If the specified second exceeds the video duration, the API may use the last frame or return an error.
156
+ 3. **Webhook Failures**: If your webhook endpoint is unavailable, you won't receive the processing result.
157
+ 4. **Large Videos**: Processing very large videos may take longer and could time out.
158
+
159
+ ## Best Practices
160
+
161
+ 1. **Use Webhooks for Long Videos**: Always use webhooks when processing large videos to avoid HTTP timeout issues.
162
+ 2. **Optimize Thumbnail Selection**: Choose meaningful timestamps for thumbnails (e.g., after intro sequences).
163
+ 3. **Error Handling**: Implement proper error handling in your application to manage API errors gracefully.
164
+ 4. **Rate Limiting**: Monitor the queue length in responses to avoid overwhelming the service.
165
+ 5. **Idempotent Requests**: Use the `id` parameter to make requests idempotent and avoid duplicate processing.
docs/video/trim.md ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Video Trim Endpoint
2
+
3
+ ## 1. Overview
4
+
5
+ The `/v1/video/trim` endpoint is part of the Video API and allows users to trim a video by removing specified portions from the beginning and/or end. It also provides optional encoding settings to control the output video quality. This endpoint fits into the overall API structure as a part of the version 1 (`v1`) routes, specifically under the `video` category.
6
+
7
+ ## 2. Endpoint
8
+
9
+ **URL Path:** `/v1/video/trim`
10
+ **HTTP Method:** `POST`
11
+
12
+ ## 3. Request
13
+
14
+ ### Headers
15
+
16
+ - `x-api-key` (required): The API key for authentication.
17
+
18
+ ### Body Parameters
19
+
20
+ - `video_url` (required, string): The URL of the video file to be trimmed.
21
+ - `start` (optional, string): The start time for trimming in the format `hh:mm:ss` or `mm:ss`.
22
+ - `end` (optional, string): The end time for trimming in the format `hh:mm:ss` or `mm:ss`.
23
+ - `video_codec` (optional, string): The video codec to be used for encoding the output video. Default is `libx264`.
24
+ - `video_preset` (optional, string): The video preset to be used for encoding the output video. Default is `medium`.
25
+ - `video_crf` (optional, number): The Constant Rate Factor (CRF) value for video encoding, ranging from 0 to 51. Default is 23.
26
+ - `audio_codec` (optional, string): The audio codec to be used for encoding the output video. Default is `aac`.
27
+ - `audio_bitrate` (optional, string): The audio bitrate to be used for encoding the output video. Default is `128k`.
28
+ - `webhook_url` (optional, string): The URL to receive a webhook notification upon completion of the task.
29
+ - `id` (optional, string): A unique identifier for the request.
30
+
31
+ The `validate_payload` directive in the routes file ensures that the request payload adheres to the specified schema, which includes the required and optional parameters, their data types, and any additional constraints.
32
+
33
+ ### Example Request
34
+
35
+ ```json
36
+ {
37
+ "video_url": "https://example.com/video.mp4",
38
+ "start": "00:01:00",
39
+ "end": "00:03:00",
40
+ "video_codec": "libx264",
41
+ "video_preset": "faster",
42
+ "video_crf": 28,
43
+ "audio_codec": "aac",
44
+ "audio_bitrate": "128k",
45
+ "webhook_url": "https://example.com/webhook",
46
+ "id": "unique-request-id"
47
+ }
48
+ ```
49
+
50
+ ```bash
51
+ curl -X POST \
52
+ https://api.example.com/v1/video/trim \
53
+ -H 'x-api-key: YOUR_API_KEY' \
54
+ -H 'Content-Type: application/json' \
55
+ -d '{
56
+ "video_url": "https://example.com/video.mp4",
57
+ "start": "00:01:00",
58
+ "end": "00:03:00",
59
+ "video_codec": "libx264",
60
+ "video_preset": "faster",
61
+ "video_crf": 28,
62
+ "audio_codec": "aac",
63
+ "audio_bitrate": "128k",
64
+ "webhook_url": "https://example.com/webhook",
65
+ "id": "unique-request-id"
66
+ }'
67
+ ```
68
+
69
+ ## 4. Response
70
+
71
+ ### Success Response
72
+
73
+ The success response follows the general response structure defined in the `app.py` file. Here's an example:
74
+
75
+ ```json
76
+ {
77
+ "endpoint": "/v1/video/trim",
78
+ "code": 200,
79
+ "id": "unique-request-id",
80
+ "job_id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
81
+ "response": "https://example.com/trimmed-video.mp4",
82
+ "message": "success",
83
+ "pid": 12345,
84
+ "queue_id": 6789,
85
+ "run_time": 5.234,
86
+ "queue_time": 0.123,
87
+ "total_time": 5.357,
88
+ "queue_length": 0,
89
+ "build_number": "1.0.0"
90
+ }
91
+ ```
92
+
93
+ ### Error Responses
94
+
95
+ - **400 Bad Request**: Returned when the request payload is missing or contains invalid parameters.
96
+
97
+ ```json
98
+ {
99
+ "code": 400,
100
+ "message": "Invalid request payload"
101
+ }
102
+ ```
103
+
104
+ - **401 Unauthorized**: Returned when the `x-api-key` header is missing or invalid.
105
+
106
+ ```json
107
+ {
108
+ "code": 401,
109
+ "message": "Unauthorized"
110
+ }
111
+ ```
112
+
113
+ - **500 Internal Server Error**: Returned when an unexpected error occurs during the video trimming process.
114
+
115
+ ```json
116
+ {
117
+ "code": 500,
118
+ "message": "An error occurred during the video trimming process"
119
+ }
120
+ ```
121
+
122
+ ## 5. Error Handling
123
+
124
+ The endpoint handles common errors such as missing or invalid parameters by returning appropriate HTTP status codes and error messages. The `validate_payload` decorator ensures that the request payload adheres to the specified schema, and any violations will result in a 400 Bad Request error.
125
+
126
+ The main application context (`app.py`) includes error handling for the task queue. If the maximum queue length is reached, the endpoint will return a 429 Too Many Requests error with a corresponding message.
127
+
128
+ ## 6. Usage Notes
129
+
130
+ - The `start` and `end` parameters are optional, but at least one of them must be provided to perform the trimming operation.
131
+ - The `video_codec`, `video_preset`, `video_crf`, `audio_codec`, and `audio_bitrate` parameters are optional and allow users to customize the encoding settings for the output video.
132
+ - The `webhook_url` parameter is optional and can be used to receive a notification when the task is completed.
133
+ - The `id` parameter is optional and can be used to uniquely identify the request.
134
+
135
+ ## 7. Common Issues
136
+
137
+ - Providing an invalid or inaccessible `video_url`.
138
+ - Specifying invalid or unsupported values for the encoding parameters (`video_codec`, `video_preset`, `video_crf`, `audio_codec`, `audio_bitrate`).
139
+ - Encountering issues with the video trimming process due to unsupported video formats or corrupted files.
140
+
141
+ ## 8. Best Practices
142
+
143
+ - Validate the `video_url` parameter to ensure it points to a valid and accessible video file.
144
+ - Use appropriate encoding settings based on the desired output quality and file size requirements.
145
+ - Implement error handling and retry mechanisms for failed requests or network issues.
146
+ - Monitor the task queue length and adjust the `MAX_QUEUE_LENGTH` value accordingly to prevent overloading the system.
147
+ - Implement rate limiting or throttling mechanisms to prevent abuse or excessive requests.
generate_docs.py ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2025 Stephen G. Pope
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
17
+
18
+
19
+ import os
20
+ import sys
21
+ import json
22
+ import requests
23
+ import time
24
+ from pathlib import Path
25
+ from datetime import datetime, timedelta
26
+
27
+ def load_config():
28
+ """Load configuration from env_shell.json file."""
29
+ config_path = Path(__file__).parent / '.env_shell.json'
30
+ try:
31
+ with open(config_path, 'r') as f:
32
+ config = json.load(f)
33
+ return config.get('ANTHROPIC_API_KEY'), config.get('API_DOC_OUTPUT_DIR')
34
+ except FileNotFoundError:
35
+ print(f"Error: Configuration file not found at: {config_path}")
36
+ sys.exit(1)
37
+ except json.JSONDecodeError:
38
+ print(f"Error: Invalid JSON in configuration file: {config_path}")
39
+ sys.exit(1)
40
+ except Exception as e:
41
+ print(f"Error loading configuration: {str(e)}")
42
+ sys.exit(1)
43
+
44
+ def load_app_context():
45
+ """Load the app.py file from the root of the repository."""
46
+ try:
47
+ # Get the root directory by going up from the current file's location
48
+ root_dir = Path(__file__).parent.parent
49
+ app_path = Path(__file__).parent / 'app.py'
50
+
51
+ if not app_path.exists():
52
+ print("Warning: app.py not found in repository root. Documentation will be generated without API context.")
53
+ return None
54
+
55
+ with open(app_path, 'r', encoding='utf-8') as f:
56
+ return f.read()
57
+ except Exception as e:
58
+ print(f"Warning: Could not load app.py: {str(e)}")
59
+ return None
60
+
61
+ # The prompt template to send to Claude
62
+ CLAUDE_PROMPT = '''
63
+
64
+ I am providing you with a Python file containing API endpoint definitions.
65
+
66
+ First, here is the main application context from app.py that shows how the API is structured and handled:
67
+
68
+ ** app.py below
69
+
70
+ {app_context}
71
+
72
+ ** app.py DONE
73
+
74
+ Now, please read through the following endpoint code and analyze it in the context of the main application:
75
+
76
+ **endpoint below
77
+
78
+ {file_content}
79
+
80
+ Please generate detailed documentation in Markdown format as follows:
81
+
82
+ 1. Overview: Describe the purpose of the endpoint and how it fits into the overall API structure shown in app.py.
83
+ 2. Endpoint: Specify the URL path and HTTP method.
84
+ 3. Request:
85
+ - Headers: List any required headers, such as the x-api-key headers.
86
+ - Body Parameters: List the required and optional parameters, including the parameter type and purpose.
87
+ - Specifically study the validate_payload directive in the routes file to build the documentation
88
+ - Example Request: Provide a sample request payload and a sample curl command.
89
+ 4. Response:
90
+ - Success Response: Reference the endpoint and general response from the app.py to show a full sample response from the api
91
+ - Error Responses: Include examples of common error status codes, with example JSON responses for each.
92
+ 5. Error Handling:
93
+ - Describe common errors, like missing or invalid parameters, and indicate which status codes they produce
94
+ - Include any specific error handling from the main application context
95
+ 6. Usage Notes: Any additional notes on using the endpoint effectively.
96
+ 7. Common Issues: List any common issues a user might encounter.
97
+ 8. Best Practices: Any recommended best practices for this endpoint.
98
+
99
+ Format the documentation with markdown headings, bullet points, and code blocks.
100
+ '''
101
+
102
+ def call_claude_api(message: str, api_key: str) -> str:
103
+ """Make a direct API call to Claude."""
104
+ headers = {
105
+ "Content-Type": "application/json",
106
+ "x-api-key": api_key,
107
+ "anthropic-version": "2023-06-01"
108
+ }
109
+
110
+ data = {
111
+ "model": "claude-3-sonnet-20240229",
112
+ "max_tokens": 4096,
113
+ "temperature": 0,
114
+ "messages": [
115
+ {"role": "user", "content": message}
116
+ ]
117
+ }
118
+
119
+ response = requests.post(
120
+ "https://api.anthropic.com/v1/messages",
121
+ headers=headers,
122
+ json=data
123
+ )
124
+
125
+ if response.status_code != 200:
126
+ raise Exception(f"API call failed with status {response.status_code}: {response.text}")
127
+
128
+ return response.json()["content"][0]["text"]
129
+
130
+ def should_skip_doc_generation(output_file: Path, force: bool = False) -> bool:
131
+ """
132
+ Check if documentation was updated in the last 24 hours.
133
+
134
+ Args:
135
+ output_file: Path to the output markdown file
136
+ force: If True, always return False to force generation
137
+
138
+ Returns:
139
+ bool: True if file was updated in the last 24 hours and not forced, False otherwise
140
+ """
141
+ # If force flag is provided, never skip
142
+ if force:
143
+ return False
144
+
145
+ if not output_file.exists():
146
+ return False
147
+
148
+ # Get file modification time
149
+ mod_time = datetime.fromtimestamp(output_file.stat().st_mtime)
150
+
151
+ # Check if file was modified in the last 24 hours
152
+ time_threshold = datetime.now() - timedelta(hours=24)
153
+
154
+ return mod_time > time_threshold
155
+
156
+ def process_single_file(source_file: Path, output_path: Path, api_key: str, force: bool = False):
157
+ """
158
+ Process a single Python file.
159
+
160
+ Args:
161
+ source_file: Path to the source Python file
162
+ output_path: Path to output the markdown file
163
+ api_key: Anthropic API key
164
+ force: If True, generate docs even if they were updated recently
165
+ """
166
+ try:
167
+ # Create output file path
168
+ if output_path.is_dir():
169
+ output_file = output_path / source_file.with_suffix('.md').name
170
+ else:
171
+ output_file = output_path
172
+
173
+ # Check if docs were recently updated
174
+ if should_skip_doc_generation(output_file, force):
175
+ print(f"Skipping {source_file} - documentation updated within the last 24 hours")
176
+ return
177
+
178
+ # Read the source file
179
+ with open(source_file, 'r', encoding='utf-8') as f:
180
+ file_content = f.read()
181
+
182
+ # Load app.py context
183
+ app_context = load_app_context()
184
+ if app_context is None:
185
+ app_context = "No app.py context available."
186
+
187
+ # Create the full prompt
188
+ message = CLAUDE_PROMPT.format(
189
+ app_context=app_context,
190
+ file_content=file_content
191
+ )
192
+
193
+ # Get documentation from Claude
194
+ markdown_content = call_claude_api(message, api_key)
195
+
196
+ # Create necessary directories
197
+ output_file.parent.mkdir(parents=True, exist_ok=True)
198
+
199
+ # Write the markdown content (will overwrite if exists)
200
+ with open(output_file, 'w', encoding='utf-8') as f:
201
+ f.write(markdown_content)
202
+
203
+ print(f"Generated documentation for: {source_file}")
204
+ print(f"Output saved to: {output_file}")
205
+
206
+ except Exception as e:
207
+ print(f"Error processing {source_file}: {str(e)}", file=sys.stderr)
208
+
209
+ def process_directory(source_dir: Path, output_dir: Path, api_key: str, force: bool = False):
210
+ """Process all Python files in the source directory recursively."""
211
+ # Track statistics
212
+ total_files = 0
213
+ processed_files = 0
214
+ skipped_files = 0
215
+ error_files = 0
216
+
217
+ start_time = time.time()
218
+
219
+ # Walk through all files in source directory
220
+ for root, _, files in os.walk(source_dir):
221
+ for file in files:
222
+ if file.endswith('.py'):
223
+ # Get the source file path
224
+ source_file = Path(root) / file
225
+ total_files += 1
226
+
227
+ try:
228
+ # Calculate relative path to maintain directory structure
229
+ rel_path = source_file.relative_to(source_dir)
230
+ output_file = output_dir / rel_path.with_suffix('.md')
231
+
232
+ # Create necessary directories
233
+ output_file.parent.mkdir(parents=True, exist_ok=True)
234
+
235
+ # Check if we should skip this file
236
+ if should_skip_doc_generation(output_file, force):
237
+ print(f"Skipping {source_file} - documentation updated within the last 24 hours")
238
+ skipped_files += 1
239
+ continue
240
+
241
+ # Process the file
242
+ process_single_file(source_file, output_file, api_key, force)
243
+ processed_files += 1
244
+
245
+ except Exception as e:
246
+ print(f"Error processing {source_file}: {str(e)}", file=sys.stderr)
247
+ error_files += 1
248
+
249
+ # Print summary
250
+ elapsed_time = time.time() - start_time
251
+ print("\nDocumentation Generation Summary:")
252
+ print(f"Total Python files found: {total_files}")
253
+ print(f"Files processed: {processed_files}")
254
+ print(f"Files skipped (updated in last 24h): {skipped_files}")
255
+ print(f"Files with errors: {error_files}")
256
+ print(f"Total time: {elapsed_time:.2f} seconds")
257
+
258
+ def main():
259
+ # Check if --force flag is provided
260
+ force_generation = False
261
+ source_path_arg = None
262
+
263
+ for arg in sys.argv[1:]:
264
+ if arg == "--force":
265
+ force_generation = True
266
+ else:
267
+ source_path_arg = arg
268
+
269
+ if not source_path_arg:
270
+ print("Usage: python script.py <source_path> [--force]")
271
+ print("Note: source_path can be either a single .py file or a directory")
272
+ print("Options:")
273
+ print(" --force: Generate documentation even if it was updated within 24 hours")
274
+ print("\nPlease ensure .env_shell.json exists in the same directory with:")
275
+ print(" ANTHROPIC_API_KEY: Your Anthropic API key")
276
+ print(" API_DOC_OUTPUT_DIR: Directory where documentation will be saved")
277
+ sys.exit(1)
278
+
279
+ # Load configuration from JSON file
280
+ api_key, output_dir = load_config()
281
+
282
+ # Validate configuration
283
+ if not api_key:
284
+ print("Error: ANTHROPIC_API_KEY not found in configuration file")
285
+ sys.exit(1)
286
+
287
+ if not output_dir:
288
+ print("Error: API_DOC_OUTPUT_DIR not found in configuration file")
289
+ sys.exit(1)
290
+
291
+ output_path = Path(output_dir)
292
+
293
+ # Get and validate source path
294
+ source_path = Path(source_path_arg)
295
+
296
+ if not source_path.exists():
297
+ print(f"Error: Source path does not exist: {source_path}")
298
+ sys.exit(1)
299
+
300
+ if source_path.is_file() and not source_path.suffix == '.py':
301
+ print("Error: Source file must be a Python file (.py)")
302
+ sys.exit(1)
303
+
304
+ # Create output directory if it doesn't exist
305
+ output_path.mkdir(parents=True, exist_ok=True)
306
+
307
+ print(f"Starting documentation generation...")
308
+ print(f"Source: {source_path}")
309
+ print(f"Output: {output_path}")
310
+ if force_generation:
311
+ print(f"Force flag enabled: Will generate all documentation regardless of last update time.\n")
312
+ else:
313
+ print(f"Note: Files updated within the last 24 hours will be skipped (use --force to override).\n")
314
+
315
+ # Process based on source type
316
+ if source_path.is_file():
317
+ # For a single file
318
+ output_file = output_path / source_path.with_suffix('.md').name if output_path.is_dir() else output_path
319
+
320
+ # Check if should skip
321
+ if should_skip_doc_generation(output_file, force_generation):
322
+ print(f"Skipping {source_path} - documentation updated within the last 24 hours")
323
+ else:
324
+ process_single_file(source_path, output_path, api_key, force_generation)
325
+ else:
326
+ process_directory(source_path, output_path, api_key, force_generation)
327
+
328
+ if __name__ == "__main__":
329
+ main()
generate_vector.sh ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ for file in $(find . -type f \( -iname "*.md" -o -iname "*.txt" -o -name "*.py" -o -name "Dockerfile" \) \
4
+ -not -name "audio_mixing.py" \
5
+ -not -name "authenticate.py" \
6
+ -not -name "authentication.py" \
7
+ -not -name "caption_video.py" \
8
+ -not -name "combine_videos.py" \
9
+ -not -name "extract_keyframes.py" \
10
+ -not -name "ffmpeg_toolkit.py" \
11
+ -not -name "file_management.py" \
12
+ -not -name "image_to_video.py" \
13
+ -not -name "media_to_mp3.py" \
14
+ -not -name "transcribe_media.py" \
15
+ -not -name "transcription.py"); do
16
+ echo "File: $file" >> "NCA Toolkit API Vector Doc.txt"
17
+ echo -e "\n\n" >> "NCA Toolkit API Vector Doc.txt"
18
+ cat "$file" >> "NCA Toolkit API Vector Doc.txt"
19
+ echo -e "\n\n" >> "NCA Toolkit API Vector Doc.txt"
20
+ done
local.sh ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Stop all running Docker containers
4
+ echo "Stopping no-code-architects running Docker containers..."
5
+ docker stop $(docker ps -a --filter ancestor=no-code-architects-toolkit:testing --format="{{.ID}}")
6
+
7
+ # Build the Docker image
8
+ echo "Building Docker image..."
9
+ docker build -t no-code-architects-toolkit:testing .
10
+
11
+ # Read variables from .variables file
12
+ echo "Reading environment variables..."
13
+ VARS=$(cat .env_variables.json)
14
+
15
+ # Function to escape JSON strings for bash
16
+ escape_json() {
17
+ echo "$1" | sed 's/"/\\"/g'
18
+ }
19
+
20
+ # Build the docker run command with environment variables
21
+ CMD="docker run -p 8080:8080"
22
+
23
+ # Add environment variables from JSON
24
+ for key in $(echo "$VARS" | jq -r 'keys[]'); do
25
+ value=$(echo "$VARS" | jq -r --arg k "$key" '.[$k]')
26
+
27
+ # Handle nested JSON (specifically for GCP_SA_CREDENTIALS)
28
+ if [[ "$key" == "GCP_SA_CREDENTIALS" ]]; then
29
+ value=$(echo "$VARS" | jq -r --arg k "$key" '.[$k]')
30
+ value=$(escape_json "$value")
31
+ fi
32
+
33
+ CMD="$CMD -e $key=\"$value\""
34
+ done
35
+
36
+ # Complete the command
37
+ CMD="$CMD no-code-architects-toolkit:testing"
38
+
39
+ # Run the Docker container
40
+ echo "Running Docker container..."
41
+ eval "$CMD"