Skip to content

スコアアルゴリズム#16

Merged
davy-yusuke merged 2 commits intomainfrom
score
Dec 14, 2025
Merged

スコアアルゴリズム#16
davy-yusuke merged 2 commits intomainfrom
score

Conversation

@davy-yusuke
Copy link
Copy Markdown
Contributor

@davy-yusuke davy-yusuke commented Dec 14, 2025

一部改善をしました。

Summary by CodeRabbit

Release Notes

  • New Features

    • Live camera-based pose scoring with real-time overlay display
    • Enhanced scoring algorithm with form bonus evaluation and motion detection
    • API debug endpoint for request inspection
    • CORS support for broader API access
  • Improvements

    • Strengthened pose visibility validation thresholds
    • Advanced confidence gating and score smoothing mechanics
    • Video segmentation capability for batch processing
  • Changes

    • API score endpoint now uses fixed width scaling

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 14, 2025

Walkthrough

This PR introduces real-time camera-based pose scoring via a new camera module, significantly refactors feature extraction and estimator logic with confidence gating and form-bonus scoring, adds CORS middleware and a debug endpoint to the API, and includes video chunking tooling.

Changes

Cohort / File(s) Summary
Configuration & Dependencies
score/.gitignore, score/pyproject.toml
.gitignore now ignores .streamlit/secrets.toml, input/chunks/*, and FitPose-Detector. pyproject.toml adds requests>=2.32.5 dependency.
API Server & Middleware
score/app.py
Added CORS middleware with permissive configuration. New /api/debug POST endpoint echoes request metadata and body. Removed annotated_output_path and save_annotated parameters from /api/score; max_width now hardcoded to 960. Updated analyze_video signature to remove annotated_output_path parameter.
Feature Extraction & Scoring Logic
score/features.py
Introduced visibility validation (VISIBLE_MEAN_MIN, shoulder width checks), confidence gating, and temporal statistics gathering. Added _form_bonus() method for activity-specific form scoring and form_score() public method. Enhanced Estimator with new state fields (min_valid_frames, smoothed_score, score_rise_up/down, margin_threshold, min_confidence_for_label) and dynamic motion flags. Reworked scoring formulas across all activity types with normalization and conditional logic paths. Added safe margin mechanism and requirement-checking.
Camera Integration
score/camera.py
New module implementing live camera-based pose scoring. Defines TemporalStats and ScoreSummary pydantic models. Provides analyze_camera() entrypoint to initialize MediaPipe pose estimator, process camera frames in real-time loop, compute pose features, update estimator, render overlay, and return aggregated summary with FPS, duration, and temporal statistics. Includes error handling for camera initialization and resource cleanup.
Build & Automation Scripts
score/input/score.sh, score/input/curl.sh
score.sh is new—splits input video into 2-second chunks using ffmpeg and POSTs each chunk to /api/score with mode=running, max_width=640. curl.sh formatting unchanged.

Sequence Diagram

sequenceDiagram
    participant User
    participant Camera as Camera Device
    participant App as analyze_camera()
    participant MediaPipe as MediaPipe Pose
    participant Estimator as Estimator
    participant Display as Screen Overlay

    User->>App: Start camera analysis
    App->>Camera: Initialize camera stream
    Camera-->>App: Frame stream ready
    
    rect rgb(200, 220, 255)
        Note over App,Display: Real-time Processing Loop
        loop Per Frame
            App->>Camera: Read frame
            Camera-->>App: Frame data
            App->>MediaPipe: Detect pose landmarks
            MediaPipe-->>App: Landmarks + visibility
            App->>Estimator: Extract features from landmarks
            Estimator-->>App: Label, score, confidence, temporal stats
            App->>Estimator: Update rolling statistics
            Estimator-->>App: Updated internal state
            App->>Display: Render overlay (label, score, stats)
        end
    end
    
    rect rgb(220, 240, 220)
        Note over App,Estimator: Final Summary Generation
        App->>Estimator: Compute aggregate metrics
        Estimator-->>App: Summary (FPS, duration, avg/max score, temporal_stats)
    end
    
    App-->>User: Return ScoreSummary (JSON)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • features.py: Dense refactoring of scoring logic with new confidence gating, form bonuses, margin thresholds, and temporal statistics collection across all activity types—requires careful verification of scoring formulas and state management.
  • camera.py: Substantial new module with MediaPipe integration, real-time frame processing loop, and orchestration between pose detection and estimator—verify resource cleanup and error handling.
  • app.py: CORS configuration and endpoint parameter changes; confirm /api/debug doesn't leak sensitive information and that hardcoded max_width=960 is intentional.
  • Integration points: Verify camera.py correctly invokes updated Estimator signatures and that temporal statistics flow correctly to output.

Possibly related PRs

  • スコア算出APIです。 #6: Modifies the same core files (score/app.py, score/features.py) and introduces the Estimator foundation that this PR extends with form bonuses, confidence gating, and temporal stats.

Poem

🐰 Through the camera's watchful lens,
Poses bloom with confidence,
Real-time scoring, refined forms,
A pose detector is reborn! 🎯

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'スコアアルゴリズム' (Score Algorithm) is vague and generic without specific details about the actual changes made in the pull request. Replace the title with a more specific description of the main changes, such as 'Add camera-based pose scoring and CORS support' or 'Enhance score estimation with temporal statistics and form validation'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch score

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (2)
score/app.py (1)

244-247: Hardcoded max_width removes client flexibility.

The max_width is now hardcoded to 960, removing the ability for clients to control video resolution. Client scripts still send max_width values that are now ignored.

Consider restoring the parameter with a default value:

 @app.post("/api/score", response_model=ScoreSummary)
 async def api_score(
     file: UploadFile = File(...),
     mode: str = Form("auto"),
+    max_width: int = Form(960),
     model_complexity: int = Form(0),
     min_det_conf: float = Form(0.5),
     min_track_conf: float = Form(0.5),
 ):

Then use the parameter value:

         summary = analyze_video(
             tmp_path,
             mode=mode,
-            max_width=960,
+            max_width=max_width,
             model_complexity=model_complexity,
score/features.py (1)

226-436: Comprehensive detection pipeline refactoring.

The refactored detect() method introduces several significant improvements:

Early exits for insufficient valid frames, a requirements-based gating mechanism, confidence thresholds, and motion-based score smoothing with rise/fall dynamics.

The logic is complex but well-structured. Consider documenting the rationale for key thresholds in the requirements dictionary for future maintainability.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87f5c47 and 4014306.

⛔ Files ignored due to path filters (1)
  • score/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • score/.gitignore (1 hunks)
  • score/app.py (4 hunks)
  • score/camera.py (1 hunks)
  • score/features.py (9 hunks)
  • score/input/curl.sh (1 hunks)
  • score/input/score.sh (1 hunks)
  • score/pyproject.toml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
score/input/score.sh (2)
frontend/app/solo.tsx (3)
  • video (54-79)
  • ScoreResponse (18-27)
  • camera (42-96)
frontend/utils/score.ts (3)
  • videoUri (37-94)
  • ScoreResponse (9-18)
  • mode (21-35)
score/camera.py (2)
score/features.py (5)
  • Estimator (89-553)
  • frame_features_from_xyvis (16-86)
  • push (126-146)
  • detect (226-436)
  • _temporal_stats (148-220)
score/app.py (3)
  • TemporalStats (30-34)
  • ScoreSummary (36-47)
  • _temporal_stats_to_dict (49-55)
score/app.py (1)
score/camera.py (1)
  • ScoreSummary (20-31)
🪛 Ruff (0.14.8)
score/camera.py

5-5: Redefinition of unused Optional from line 1

Remove definition: Optional

(F811)


5-5: Redefinition of unused List from line 1

Remove definition: List

(F811)


5-5: Redefinition of unused Dict from line 1

Remove definition: Dict

(F811)


43-43: Unpacked variable h is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


72-72: Avoid specifying long messages outside the exception class

(TRY003)


80-80: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


81-81: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)

score/features.py

98-98: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


436-436: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)

score/app.py

196-196: Do not catch blind exception: Exception

(BLE001)


212-212: Do not catch blind exception: Exception

(BLE001)


225-225: Do not perform function call File in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

🪛 Shellcheck (0.11.0)
score/input/score.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🔇 Additional comments (8)
score/.gitignore (1)

216-219: LGTM!

The added ignore patterns appropriately exclude secrets (.streamlit/secrets.toml), generated video chunks (input/chunks/*), and external detector artifacts (FitPose-Detector).

score/camera.py (1)

52-174: Core camera analysis logic looks solid.

The analyze_camera function correctly:

  • Initializes MediaPipe Pose with proper parameters
  • Handles camera resource lifecycle in a finally block
  • Processes frames with feature extraction and scoring
  • Aggregates statistics and returns a structured summary
score/features.py (5)

9-14: LGTM on new constants and helper.

The new constants (VISIBLE_MEAN_MIN, MIN_SHOULDER_WIDTH_PX, DEFAULT_MIN_VALID_SECONDS) provide clear thresholds for visibility and quality checks. The safe_mean helper properly handles empty arrays.


16-86: Improved robustness with visibility and size checks.

The function now validates visibility with VISIBLE_MEAN_MIN and checks shoulder width against MIN_SHOULDER_WIDTH_PX, preventing invalid detections from low-quality frames. The epsilon additions in normalization prevent division-by-zero errors.


88-125: Enhanced estimator state management.

The new initialization adds smoothing parameters and confidence thresholds, improving score stability and detection reliability. The stable_threshold default increased to 4, requiring more consistent frames before label changes.


148-220: LGTM on temporal statistics improvements.

The FFT calculation now guards against edge cases with a positivity check on yf[idx], and visible_mean is included in the stats dictionary for downstream quality checks.


438-553: Well-structured form scoring implementation.

The _form_bonus and form_score methods provide activity-specific scoring with consistent patterns. Each activity has tailored metrics (depth for squats, torso angle for pushups, etc.) that are normalized and combined with appropriate weights.

score/pyproject.toml (1)

13-13: No action required. requests>=2.32.5 is the current latest version with all known critical security vulnerabilities (CVE-2024-47081, CVE-2024-35195) already resolved in earlier 2.32.x releases. This version has no unresolved CVEs and is secure.

Comment on lines +22 to +28
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restrict CORS origins for production security.

The CORS middleware allows all origins (allow_origins=["*"]), which exposes the API to cross-origin requests from any domain. In production, this creates security risks including CSRF attacks.

Restrict allow_origins to known, trusted domains:

 app.add_middleware(
     CORSMiddleware,
-    allow_origins=["*"],
+    allow_origins=["http://localhost:3000", "https://yourdomain.com"],
     allow_credentials=True,
     allow_methods=["*"],
     allow_headers=["*"],
 )

Consider using environment variables to configure allowed origins per deployment environment.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "https://yourdomain.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
🤖 Prompt for AI Agents
In score/app.py around lines 22-28 the CORS middleware is configured with
allow_origins=["*"], which is too permissive for production; replace the
wildcard with a configurable list of trusted origins (read from an environment
variable like ALLOWED_ORIGINS that contains a comma-separated list), parse that
variable into a Python list and pass it to allow_origins, and keep a safe
fallback for local dev (e.g., ["http://localhost:3000"]) when the env var is
unset; also ensure allow_credentials is only True when specific origins are set
(not "*") and document the env var usage in deployment configs.

Comment on lines +179 to +220
@app.post("/api/debug")
async def debug_request(request: Request):
info = {}

info["method"] = request.method
info["url"] = str(request.url)
info["headers"] = dict(request.headers)

info["content_type"] = request.headers.get("content-type")

info["query_params"] = dict(request.query_params)

body = await request.body()
info["body_raw_length"] = len(body)

try:
info["body_raw_preview"] = body[:1000].decode("utf-8", errors="replace")
except Exception:
info["body_raw_preview"] = str(body[:1000])

form_data = {}
files = {}

try:
form = await request.form()
for key, value in form.items():
if hasattr(value, "filename"):
files[key] = {
"filename": value.filename,
"content_type": value.content_type,
}
else:
form_data[key] = value
except Exception as e:
info["form_parse_error"] = str(e)

info["form_fields"] = form_data
info["files"] = files

print(info)

return JSONResponse(content=info)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove or secure the debug endpoint before production.

The /api/debug endpoint exposes request metadata, headers, and body content without authentication. Headers may contain sensitive data like authorization tokens, and the body preview could leak PII.

Options:

  1. Remove entirely if only needed for development
  2. Add authentication and restrict to admin users
  3. Use conditional registration based on environment:
+import os
+
+if os.getenv("DEBUG_MODE") == "true":
+    @app.post("/api/debug")
+    async def debug_request(request: Request):
+        # ... existing code

Never deploy this endpoint to production without proper access controls.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.8)

196-196: Do not catch blind exception: Exception

(BLE001)


212-212: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
In score/app.py around lines 179 to 220 the /api/debug endpoint is exposing
request headers, body previews and other metadata without any authentication
which can leak sensitive data; remove the endpoint for production or secure it:
either delete this handler entirely if only used in development, or
conditionally register it only when an environment flag (e.g., DEBUG=true) is
set, and/or add strict authentication/authorization (require an admin token or
valid user dependency) before returning any data; additionally redact sensitive
headers (Authorization, Cookie, etc.) and limit or remove body previews to avoid
PII leakage when enabling this endpoint.

min_track_conf: float = Form(0.5),
save_annotated: bool = Form(False),
):
print(file)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Replace print statement with structured logging.

The print(file) statement appears to be debug code. Use proper logging for observability in production.

Apply this diff:

+import logging
+
+logger = logging.getLogger(__name__)
+
 @app.post("/api/score", response_model=ScoreSummary)
 async def api_score(
     file: UploadFile = File(...),
     mode: str = Form("auto"),
     model_complexity: int = Form(0),
     min_det_conf: float = Form(0.5),
     min_track_conf: float = Form(0.5),
 ):
-    print(file)
+    logger.info(f"Processing upload: {file.filename}, size: {file.size}, mode: {mode}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
print(file)
logger.info(f"Processing upload: {file.filename}, size: {file.size}, mode: {mode}")
🤖 Prompt for AI Agents
In score/app.py around line 231, replace the debug print(file) with structured
logging: remove the print call, obtain or create the module logger (e.g. logger
= logging.getLogger(__name__) if not present), and emit a log entry with an
appropriate level (debug or info) that includes the filename and any relevant
context as explicit fields (e.g. logger.debug("processing file", extra={"file":
file}) or logger.debug("processing file=%s", file)); ensure imports for logging
exist and avoid logging sensitive contents.

Comment on lines +1 to +5
from typing import Dict, List, Optional

import numpy as np
import time
from typing import Optional, List, Dict
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove duplicate imports.

Lines 1 and 5 both import Optional, List, and Dict from typing, causing redefinition warnings.

Apply this diff:

 from typing import Dict, List, Optional
 
 import numpy as np
 import time
-from typing import Optional, List, Dict
 
 import cv2
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from typing import Dict, List, Optional
import numpy as np
import time
from typing import Optional, List, Dict
from typing import Dict, List, Optional
import numpy as np
import time
🧰 Tools
🪛 Ruff (0.14.8)

5-5: Redefinition of unused Optional from line 1

Remove definition: Optional

(F811)


5-5: Redefinition of unused List from line 1

Remove definition: List

(F811)


5-5: Redefinition of unused Dict from line 1

Remove definition: Dict

(F811)

🤖 Prompt for AI Agents
In score/camera.py around lines 1 to 5, there are duplicate typing imports
(Optional, List, Dict) on lines 1 and 5; remove the redundant second "from
typing import Optional, List, Dict" line so the file has only a single import
statement for those types (keep the first or consolidate into one import), and
ensure import ordering remains consistent (typing once, then third-party like
numpy, then stdlib like time).

Comment on lines +14 to +39
class TemporalStats(BaseModel):
dom_freq: Optional[float] = None
periodic_strength: Optional[float] = None
ankle_speed_norm: Optional[float] = None
hip_y_std_norm: Optional[float] = None

class ScoreSummary(BaseModel):
frames_processed: int
input_fps: float
duration_seconds: float
mode: str
avg_score: Optional[float] = None
max_score: Optional[int] = None
last_label: Optional[str] = None
last_score: Optional[int] = None
last_conf: Optional[float] = None
temporal_stats: Optional[TemporalStats] = None
processing_time_seconds: float

def _temporal_stats_to_dict(med: Dict) -> Dict:
return {
"dom_freq": med.get("dom_freq"),
"periodic_strength": med.get("periodic_strength"),
"ankle_speed_norm": med.get("ankle_speed_norm"),
"hip_y_std_norm": med.get("hip_y_std_norm"),
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Extract duplicated models to a shared module.

The TemporalStats, ScoreSummary classes and _temporal_stats_to_dict function are duplicated between this file and score/app.py (lines 30-55). This violates DRY principles.

Create a new file score/models.py:

from typing import Optional, Dict
from pydantic import BaseModel

class TemporalStats(BaseModel):
    dom_freq: Optional[float] = None
    periodic_strength: Optional[float] = None
    ankle_speed_norm: Optional[float] = None
    hip_y_std_norm: Optional[float] = None

class ScoreSummary(BaseModel):
    frames_processed: int
    input_fps: float
    duration_seconds: float
    mode: str
    avg_score: Optional[float] = None
    max_score: Optional[int] = None
    last_label: Optional[str] = None
    last_score: Optional[int] = None
    last_conf: Optional[float] = None
    temporal_stats: Optional[TemporalStats] = None
    processing_time_seconds: float

def temporal_stats_to_dict(med: Dict) -> Dict:
    return {
        "dom_freq": med.get("dom_freq"),
        "periodic_strength": med.get("periodic_strength"),
        "ankle_speed_norm": med.get("ankle_speed_norm"),
        "hip_y_std_norm": med.get("hip_y_std_norm"),
    }

Then import in both files:

from score.models import TemporalStats, ScoreSummary, temporal_stats_to_dict
🤖 Prompt for AI Agents
In score/camera.py around lines 14 to 39 the TemporalStats and ScoreSummary
models and the _temporal_stats_to_dict function are duplicated elsewhere;
extract these into a new shared module score/models.py (define TemporalStats,
ScoreSummary and temporal_stats_to_dict there using the provided signatures and
types), remove the local class/function definitions from score/camera.py, and
replace them with imports from score.models: from score.models import
TemporalStats, ScoreSummary, temporal_stats_to_dict; ensure names match (rename
_temporal_stats_to_dict to temporal_stats_to_dict) and update any local
references.

Comment on lines 1 to +4
curl -X POST "http://localhost:8000/api/score" \
-F "file=@input.mp4" \
-F "mode=running" \
-F "max_width=640" No newline at end of file
-F "max_width=640"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Parameter sent but ignored by the API.

The script sends max_width=640 to /api/score, but the API now hardcodes max_width=960, ignoring this parameter entirely. This creates confusion about which value is actually used.

Consider either removing the max_width parameter from this script or updating it to match the hardcoded value (960) for consistency. Alternatively, restore the API's ability to accept this parameter if client-side control is needed.

🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In score/input/curl.sh around lines 1 to 4, the script sends max_width=640 but
the API hardcodes max_width=960 so the passed parameter is ignored; either
remove the max_width form field from this curl script, or change its value to
960 to match the server, or if you prefer client control, update the server to
read and respect the max_width form parameter; pick one approach and apply it so
the script and API are consistent (remove or update the client parameter to 960,
or modify the API to parse and use the submitted max_width).

Comment on lines +1 to +9
mkdir -p chunks

ffmpeg -i input.mp4 \
-c copy \
-map 0 \
-f segment \
-segment_time 2 \
-reset_timestamps 1 \
chunks/part_%03d.mp4
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add shebang to specify the shell interpreter.

The script lacks a shebang line, making it unclear which shell should execute it.

Apply this diff to add a shebang:

+#!/bin/bash
 mkdir -p chunks
 
 ffmpeg -i input.mp4 \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mkdir -p chunks
ffmpeg -i input.mp4 \
-c copy \
-map 0 \
-f segment \
-segment_time 2 \
-reset_timestamps 1 \
chunks/part_%03d.mp4
#!/bin/bash
mkdir -p chunks
ffmpeg -i input.mp4 \
-c copy \
-map 0 \
-f segment \
-segment_time 2 \
-reset_timestamps 1 \
chunks/part_%03d.mp4
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In score/input/score.sh around lines 1 to 9, the script is missing a shebang so
the shell interpreter is ambiguous; add a shebang as the first line (e.g.,
#!/bin/sh or #!/usr/bin/env bash depending on required features) so the script
will be executed with the intended shell, then keep the existing mkdir and
ffmpeg commands unchanged.

Comment on lines +14 to +17
curl -X POST "http://localhost:8000/api/score" \
-F "file=@${file}" \
-F "mode=running" \
-F "max_width=640"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Parameter sent but ignored by the API.

The script sends max_width=640 to /api/score, but the API now hardcodes max_width=960, making this parameter ineffective.

Consider removing the max_width parameter or updating it to 960 for consistency. This duplicates the issue in curl.sh.

🤖 Prompt for AI Agents
In score/input/score.sh around lines 14 to 17, the script sends max_width=640 to
/api/score but the server now hardcodes max_width=960 so the parameter is
ignored; update the client to match the server by either removing the max_width
parameter entirely or changing its value to 960 (and apply the same change to
curl.sh to keep both callers consistent).

@davy-yusuke davy-yusuke merged commit 6064606 into main Dec 14, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant