Skip to content

Commit 69be527

Browse files
Resolved an issue where the first streamed output could incorrectly return the input file.
1 parent f0e2ed6 commit 69be527

4 files changed

Lines changed: 84 additions & 25 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [1.0.1] - 2025-12-20
6+
7+
### Fixed
8+
9+
- Resolved an issue where the first streamed output could incorrectly return the input file.
10+
11+
### Added
12+
13+
- Added S3 configuration documentation to the README.
14+
- Expanded README with an explanation of parallel processing behavior.
15+
516
## [1.0.0] - 2025-12-20
617

718
### Added

README.md

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ You provide input files and FFmpeg commands; the API returns the results via **S
1515

1616
`POST /v1/process`
1717

18+
### API Example
19+
20+
```bash
21+
curl -X POST http://localhost:8080/v1/process \
22+
-H "Content-Type: application/json" \
23+
-d '{
24+
"input": {
25+
"input.mp4": { "http": "https://example.com/video.mp4" }
26+
},
27+
"commands": [
28+
["-i", "input.mp4", "-vn", "output.mp3"]
29+
],
30+
"output": { "base64": true }
31+
}'
32+
```
33+
1834
## Request Structure
1935

2036
```json
@@ -91,24 +107,36 @@ Filenames reference input files or outputs from previous commands.
91107
}
92108
```
93109

94-
## Example
110+
## S3 Configuration
95111

96-
```bash
97-
curl -X POST http://localhost:8080/v1/process \
98-
-H "Content-Type: application/json" \
99-
-d '{
100-
"input": {
101-
"input.mp4": { "http": "https://example.com/video.mp4" }
102-
},
103-
"commands": [
104-
["-i", "input.mp4", "-vn", "output.mp3"]
105-
],
106-
"output": { "base64": true }
107-
}'
112+
S3 access is configured **per request** using the `s3Config` object.
113+
114+
* Works with:
115+
* AWS S3
116+
* S3-compatible providers (MinIO, DigitalOcean Spaces, Cloudflare R2, etc.)
117+
* The `endpoint` should **not** include a bucket name
118+
119+
* `useSSL` defaults to **true** if omitted
120+
121+
### Example
122+
123+
```json
124+
{
125+
"s3Config": {
126+
"endpoint": "s3.amazonaws.com",
127+
"region": "us-east-1",
128+
"accessKey": "AKIA...",
129+
"secretKey": "SECRET...",
130+
"useSSL": true
131+
}
132+
}
108133
```
109134

110135
## Docker
111136

137+
* FFmpeg is bundled
138+
* No external dependencies
139+
112140
### Image
113141

114142
```
@@ -127,10 +155,23 @@ API available at:
127155
http://localhost:8080
128156
```
129157

130-
## Notes
158+
## Scaling & Concurrency
131159

132-
* FFmpeg is bundled
133-
* No external dependencies
134-
* Temporary files are cleaned automatically
135-
* S3 credentials are supplied per request
136-
* Go binary on scratch image
160+
Each request is handled independently by the HTTP server.
161+
162+
* Input files are fetched **in parallel** (HTTP, S3, Base64 decoding).
163+
* FFmpeg is executed as a separate OS process per request.
164+
165+
Concurrency comes from handling multiple HTTP requests simultaneously. FFmpeg’s own multithreading is fully supported and can be controlled via standard flags such as:
166+
167+
```bash
168+
-threads 0 # auto
169+
-threads 4 # fixed
170+
```
171+
172+
The service is stateless:
173+
174+
* No shared filesystem state
175+
* No in-memory session data
176+
177+
This makes it easy to scale **horizontally** by running multiple instances behind a load balancer, for example using **Kubernetes**, or a managed container service.

SECURITY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ The following table outlines the versions of this project
66
currently supported with security updates:
77

88
| Version | Supported |
9-
|---------| ------------------ |
9+
|---------|--------------------|
10+
| 1.0.1 | :white_check_mark: |
1011
| 1.0.0 | :white_check_mark: |
1112

1213
## Reporting a Vulnerability

cmd/main.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"encoding/base64"
66
"encoding/json"
7-
"ffmpeg/internal"
87
"fmt"
98
"net/http"
109
"os"
@@ -17,12 +16,16 @@ import (
1716
"github.com/google/uuid"
1817

1918
"ffmpeg/api"
19+
"ffmpeg/internal"
2020
)
2121

2222
func main() {
2323
http.HandleFunc("/v1/process", handleProcess)
24+
if err := http.ListenAndServe(":8080", nil); err != nil {
25+
fmt.Println("server failed to start:", err)
26+
os.Exit(1)
27+
}
2428
fmt.Println("Listening on :8080")
25-
http.ListenAndServe(":8080", nil)
2629
}
2730

2831
func handleProcess(w http.ResponseWriter, r *http.Request) {
@@ -54,7 +57,7 @@ func handleProcess(w http.ResponseWriter, r *http.Request) {
5457
}
5558

5659
if req.Output.InlineContentType != "" {
57-
streamFirstFile(w, r, jobPath, req.Output.InlineContentType)
60+
streamFirstResult(w, r, jobPath, req)
5861
return
5962
}
6063

@@ -165,11 +168,14 @@ func collectResults(s3Client *s3.Client, req api.ProcessRequest, jobPath string)
165168
return results, nil
166169
}
167170

168-
func streamFirstFile(w http.ResponseWriter, r *http.Request, jobPath, contentType string) {
171+
func streamFirstResult(w http.ResponseWriter, r *http.Request, jobPath string, req api.ProcessRequest) {
169172
files, _ := os.ReadDir(jobPath)
170173
for _, f := range files {
171174
if !f.IsDir() {
172-
w.Header().Set("Content-Type", contentType)
175+
if _, isInput := req.Inputs[f.Name()]; isInput {
176+
continue
177+
}
178+
w.Header().Set("Content-Type", req.Output.InlineContentType)
173179
http.ServeFile(w, r, filepath.Join(jobPath, f.Name()))
174180
return
175181
}

0 commit comments

Comments
 (0)