-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/gateway unified analysis #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ Deploy Preview for crowncode-by-rthur ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds Spotify track URL analysis support to the AI Music Detection feature and improves the preview mode experience with enhanced randomness and minimum processing duration. The changes enable the application to accept both YouTube and Spotify URLs, parse them consistently, and display source-appropriate results while maintaining preview mode functionality when the backend is unavailable.
Key changes include:
- Added Spotify source type support throughout the analysis pipeline with new types and parsing logic
- Introduced jitter and clamping to confidence and feature scores for more realistic preview results
- Added minimum analysis duration (1.2s) to prevent unrealistically fast responses
- Created a new Netlify function to proxy analysis requests to the inference backend
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| platform/hooks/analysisTypes.ts | Defines new SpotifySourceInfo type and extends AnalysisSource union |
| platform/hooks/useYouTubeAnalysis.ts | Adds Spotify URL parsing, updates result builders to handle both YouTube and Spotify sources, implements minimum duration guarantee |
| platform/hooks/useFileAnalysis.ts | Updates preview confidence calculation with jitter and clamping |
| platform/hooks/analysisUtils.ts | Adds jitter and clamping utilities for more varied preview scores |
| platform/pages/ai-music-detection/index.tsx | Updates UI to display Spotify-specific source information |
| platform/netlify/functions/analyze.js | New proxy function to forward analysis requests to external inference service |
| netlify.toml | Disables Netlify secrets scan for build environment |
| docs/notes/ai-preview-mode.md | Documents preview mode behavior and limitations (with encoding issues) |
Comments suppressed due to low confidence (2)
platform/hooks/useYouTubeAnalysis.ts:262
- The fallbackToPreview function is now async and uses await internally (line 256), but it's called without await on lines 272, 291, and 297 (visible in wider context). This means the function will set state and return control immediately without waiting for the minimum duration delay. While the state updates will still happen, the timing guarantee (ensuring at least minDurationMs elapsed) won't be respected for these fallback cases. All calls to fallbackToPreview should use await, or the function should not be async if fire-and-forget is intended.
const fallbackToPreview = async (warningKey?: string) => {
await ensureMinDuration()
const elapsedSec = (Date.now() - startTimeRef.current) / 1000
const warningsBuffer = warningKey ? [warningKey] : []
setAnalysisResult(buildPreviewResult(parsed, url, elapsedSec, warningsBuffer))
setWarnings(warningsBuffer)
setProcessingState('complete')
}
netlify.toml:12
- Disabling Netlify's secrets scan (SECRETS_SCAN_ENABLED = "false") is a security concern that could allow sensitive credentials to be accidentally committed. This setting should only be used if there's a specific technical reason and should be documented. If this is needed due to false positives, consider using .gitignore or Netlify's secret exclusion patterns instead.
SECRETS_SCAN_ENABLED = "false"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const baseConfidence = 0.55 + seed * 0.35 | ||
| const confidence = Number(Math.min(0.97, Math.max(0.51, baseConfidence + (Math.random() - 0.5) * 0.08)).toFixed(3)) |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The confidence calculation uses Math.random() which produces non-deterministic results. This means the same track/video analyzed twice will show different confidence values, even though the preview mode is supposed to simulate consistent results based on a deterministic seed. Consider using a seeded random function or removing randomness from the confidence calculation to maintain consistency with the deterministic approach used for feature scores.
| const clamp01 = (value: number) => Math.min(0.99, Math.max(0, value)) | ||
|
|
||
| const jitter = (value: number, magnitude: number) => { | ||
| const delta = (Math.random() - 0.5) * magnitude |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The jitter function uses Math.random() which produces non-deterministic results. This means feature scores will vary on each analysis of the same source, breaking the deterministic seed-based approach. According to the PR description, preview mode should use "rastgele tohum + jitter" but the jitter makes results inconsistent between runs. If varied results on each call are desired, this is working as intended. However, if consistent results per source are expected (as suggested by the deterministic seed), consider using a seeded random generator for jitter as well.
| const delta = (Math.random() - 0.5) * magnitude | |
| const hash = fnv1a(value.toString()) | |
| const rand = (hash % 1000000) / 1000000 | |
| const delta = (rand - 0.5) * magnitude |
| {source.kind === 'spotify' && ( | ||
| <> | ||
| <div className={styles['result-source-item']}> | ||
| <span>Spotify Track</span> |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The label "Spotify Track" is hardcoded in English and doesn't use the translation system like other labels in this section. This breaks internationalization support. Consider adding a translation key such as t.aiDetection.result.spotifyTrack to maintain consistency with the YouTube videoId field on line 211.
| <span>Spotify Track</span> | |
| <span>{t.aiDetection.result.spotifyTrack}</span> |
| isAIGenerated, | ||
| confidence, | ||
| processingTime: elapsedSec, | ||
| modelVersion: 'youtube-preview-v1', |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The modelVersion is hardcoded as 'youtube-preview-v1' even for Spotify tracks. Consider using a more generic name like 'preview-v1' or dynamically setting it based on the source type to accurately reflect what's being analyzed.
| modelVersion: 'youtube-preview-v1', | |
| modelVersion: parsed.kind === 'spotify' ? 'spotify-preview-v1' : 'youtube-preview-v1', |
| const baseConfidence = 0.55 + seed * 0.35 | ||
| const confidence = Number(Math.min(0.97, Math.max(0.51, baseConfidence + (Math.random() - 0.5) * 0.08)).toFixed(3)) |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The confidence calculation uses Math.random() which produces non-deterministic results. This means the same file analyzed twice will show different confidence values, even though the preview mode is supposed to simulate consistent results based on a deterministic seed. Consider using a seeded random function or removing randomness from the confidence calculation to maintain consistency with the deterministic approach used for feature scores.
| if (isSpotifyHost) { | ||
| const parts = path.split('/').filter(Boolean) | ||
| const trackIndex = parts.findIndex((p) => p === 'track') | ||
| const trackId = trackIndex >= 0 ? parts[trackIndex + 1] : null |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spotify track URLs may include query parameters (e.g., ?si=...) that should be stripped when extracting the track ID. The current implementation extracts everything after '/track/' without removing query parameters, which could result in an invalid track ID. Consider using url.searchParams or splitting on '?' to extract only the track ID portion.
| kind: 'youtube', | ||
| url, | ||
| normalizedUrl: response.source.normalized_url, | ||
| videoId: response.source.video_id, |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BackendResponse interface assumes the source field will always have a video_id property (line 28), but this field won't be present for Spotify tracks. When the backend returns a Spotify response, accessing response.source.video_id will be undefined, which could cause issues if this field is used elsewhere. Consider making video_id optional or adding a track_id field to handle Spotify responses properly.
| videoId: response.source.video_id, | |
| videoId: response.source.video_id ?? parsed.videoId, |
| - Model henüz entegre edilmediğinden önizleme sonuçları rastgele tohum + jitter ile çalışıyor; güven ve feature skorları her çağrıda hafif farklı olabilir. | ||
| - Gerçek model servisi geldiğinde: | ||
| 1) /api/analyze gateway'ini harici inference servisine bağla (yt-dlp + ffmpeg + model). | ||
| 2) Önizleme jitter'ini kaldır, gerçek skorları dön. | ||
| - Gateway hedefi: INFERENCE_API_URL veya NEXT_PUBLIC_API_URL /api/analyze | ||
| - Limitler: max 30MB, ~6dk ses; Spotify/Apple şimdilik 501/preview. |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation file contains corrupted Turkish characters (e.g., "hen�z", "�nizleme", "�al���yor"). This appears to be an encoding issue. The file should be saved with UTF-8 encoding to preserve special characters correctly.
| [build.environment] | ||
| NODE_VERSION = "20" | ||
| NODE_OPTIONS = "--max-old-space-size=4096" | ||
| SECRETS_SCAN_ENABLED = "false" |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disabling Netlify's secret scanning by setting SECRETS_SCAN_ENABLED = "false" weakens your build-time defenses and increases the risk that accidentally committed credentials or other secrets pass through CI/CD undetected and end up exposed in artifacts or logs. An attacker who obtains access to the repository or build outputs would more easily discover usable secrets that would otherwise have been flagged and blocked. Unless there is a strong, documented justification and compensating controls, you should keep secret scanning enabled (or enforce an equivalent control elsewhere) to maintain protection against leaked credentials.
| SECRETS_SCAN_ENABLED = "false" |

This pull request adds support for Spotify track analysis in the AI Music Detection preview mode, alongside various improvements to the preview logic and user experience. The changes enable the app to accept Spotify track URLs, parse and process them similarly to YouTube links, and display results accordingly. Additionally, the preview mode's randomness and timing logic have been refined for more realistic and consistent user feedback.
Spotify Support Integration:
SpotifySourceInfotype and updated theAnalysisSourceunion type to include Spotify tracks inanalysisTypes.ts.parseYouTubeUrlfunction (renamed internally to handle multiple sources) to recognize and parse Spotify track URLs, returning a newParsedSourcetype that distinguishes between YouTube and Spotify. [1] [2] [3] [4]useYouTubeAnalysis.ts. [1] [2] [3] [4] [5]ai-music-detection/index.tsxto display Spotify-specific source details in the results panel. [1] [2]Preview Mode and User Experience Improvements:
analysisUtils.tsanduseFileAnalysis.ts. [1] [2] [3]Documentation and Configuration:
ai-preview-mode.md) outlining the preview mode's current behavior, limitations, and future integration steps.