hoangsonww/Moodify-Emotion-Music-App

Feature: Mood Session - Real-time Emotion Blending & Goal-Oriented Playlists (Match / Boost / Calm)

Open

#11 opened on Aug 17, 2025

View on GitHub
 (0 comments) (0 reactions) (1 assignee)JavaScript (23 forks)auto 404
bugdocumentationduplicateenhancementgood first issuehelp wanted

Repository metrics

Stars
 (80 stars)
PR merge metrics
 (PR metrics pending)

Description

Summary

Introduce a Mood Session mode that continuously fuses multimodal emotions (text / speech / facial) into a single blended mood vector and generates a dynamic Spotify playlist aligned to a user-selected goal:

  • Match my mood,
  • Boost (increase energy/valence), or
  • Calm (decrease energy/tempo).

The session adapts in real time to incoming signals and user feedback (like/skip), updating track choices and crossfading smoothly.


Motivation

  • Current flow is single-shot: detect → recommend. Users often want continuous, adaptive music as their mood shifts.
  • Goal framing (Match/Boost/Calm) supports emotion regulation, not just reflection—improving engagement and session length.
  • Real-time feedback (skips/likes) gives learning signals to improve recs and evaluate model quality.

Goals

  1. Start/Stop Mood Session with a goal selector (Match/Boost/Calm).
  2. Multimodal blend: fuse text/speech/facial scores into one mood vector (e.g., arousal/valence + discrete labels).
  3. Adaptive playlist: pick tracks by Spotify audio features (valence, energy, tempo, danceability) + genres; refresh as the mood updates.
  4. Realtime updates: react to new detections and user actions (like/skip/seek) within the session.
  5. Crossfade and smooth transitions; maintain a small look-ahead queue.
  6. Privacy controls: clear camera/mic consent; local preview of raw signals; easy pause.
  7. Telemetry: session metrics, regulation success (mood delta), skips/likes, latency.

Non-Goals (for this issue):

  • Long-term personalization models, collaborative filtering across users, social features.

User Stories

  • As a user, I can select Match/Boost/Calm and start a session that updates songs as my mood changes.
  • As a user, I can see why a track was picked (e.g., “high valence & medium energy to boost your mood”).
  • As a user, I can like/skip tracks to influence upcoming recommendations.
  • As a privacy-aware user, I can pause camera/mic at any time and keep running with text-only.

Acceptance Criteria

  • Start/Stop controls visible on Home and Results pages; goal toggle persists per session.
  • Multimodal detections update a blended mood vector at ≤1s p95 from receipt → fusion.
  • Next track selection occurs in ≤1.5s p95 after a new mood signal or skip.
  • Queue maintains ≥3 upcoming tracks; crossfade between tracks without audible gaps.
  • Explain-why tooltip available for each track (surface key audio features + goal).
  • Mobile parity: start/stop, goal selection, likes/skips; microphone/camera permissions handled natively.
  • If no camera/mic consent, session runs with available modalities (degraded state shown).
  • A11y: keyboard navigable controls, ARIA labels, focus states.

UX Notes

  • Session Bar (sticky): [● live] Current mood badge → goal chip (Match/Boost/Calm) → Like/Skip → Pause input → End Session.
  • Now Playing Card: album art, reason “why”, mood + audio features mini-pill (valence↑, energy→, tempo→).
  • Settings: sliders for tempo/energy bounds and explicit content toggle.

API (Django REST — proposed)

Align with existing URL conventions; adjust names as needed.

POST   /api/session/start
body: { userId, goal: "match"|"boost"|"calm", modalities: {text?:bool,speech?:bool,face?:bool} }

POST   /api/session/stop
body: { sessionId }

POST   /api/session/signal
body: { sessionId, signal: { modality:"text"|"speech"|"face", scores:{ valence:number, arousal:number, label:string }, ts?:string } }

GET    /api/session/next
query: sessionId
# returns next track(s), queue state, rationale

POST   /api/session/feedback
body: { sessionId, trackId, action:"like"|"skip"|"played", positionMs?:number }

GET    /api/session/state
query: sessionId
# returns blended mood vector, goal, queue, last update

Response example (/api/session/next):

{
  "tracks": [
    {
      "trackId": "spotify:track:123",
      "title": "Sunrise Drive",
      "artist": "Night Parade",
      "features": { "valence": 0.78, "energy": 0.62, "tempo": 118 },
      "rationale": "Boost: higher valence than current mood, moderate energy for smooth transition",
      "previewUrl": "https://p.scdn.co/mp3-preview/..."
    }
  ],
  "queueSize": 4,
  "blendedMood": { "valence": 0.41, "arousal": 0.55, "label": "melancholic" }
}

Blending & Ranking (AI/ML)

  • Fusion: weighted average over normalized modality confidence (dropout-robust; if a modality is missing, re-normalize).

  • Goal transform:

    • Match: minimize distance to current mood.
    • Boost: target ↑valence (+Δ), cap energy to user preference.
    • Calm: target ↓arousal/tempo, maintain moderate valence.
  • Retrieval: filter candidate tracks by Spotify audio features & user constraints → rank by (goal distance + popularity penalty + freshness).

  • Online learning: update per-user short-term weights from likes/skips within session scope.


Data Model (MongoDB examples)

  • sessions: { _id, userId, goal, active, blendedMood{valence,arousal,label}, modalities, createdAt, updatedAt }
  • session_events: { sessionId, type: "signal"|"feedback"|"track_play", payload, ts }
  • user_prefs: { userId, bounds:{tempo:[min,max], energy:[min,max]}, explicitAllowed:bool }

Privacy & Security

  • Explicit consent prompts for mic/camera; store consent state locally, not on server.
  • Allow “text-only” mode.
  • Rate-limit /signal and /feedback to prevent abuse.
  • Never store raw audio/video; only derived scores + timestamps.

Performance

  • Keep an in-memory candidate pool per session for fast re-ranking.
  • Redis cache for common seed sets (per goal).
  • Pre-fetch next track’s preview and metadata; crossfade via frontend audio element or Spotify SDK bridge where possible.

Analytics / Metrics

Events:

  • session_start {goal, modalities}
  • session_signal {modality, latencyMs}
  • session_track_recommended {trackId, features, goal}
  • session_feedback {action, trackId} KPIs:
  • Avg session duration, tracks per session, skip rate, mood regulation delta (target vs actual after N tracks), p95 recommendation latency.

Rollout Plan

  1. Phase 1: Backend session lifecycle + fusion + basic ranking; web UI; likes/skip.
  2. Phase 2: Crossfade, queue look-ahead, explanations; mobile parity.
  3. Phase 3: Personalization (short-term learning), advanced settings, A/B for goal transforms.

Tasks

Backend (Django/DRF)

  • Define sessions & session_events collections/models.
  • Implement /session/* endpoints + auth + rate limits.
  • Integrate Spotify features search (valence/energy/tempo/danceability).
  • Fusion & goal transform logic; candidate pool + re-ranker.
  • Unit/integration tests; load test p95 targets.

AI/ML

  • Normalize modality outputs; confidence weighting & dropout handling.
  • Map discrete labels ↔ (valence, arousal).
  • Online feedback updates (lightweight, session-scoped).
  • Quality dashboards (regulation delta, skip correlation).

Frontend (React)

  • Session bar + goal toggle; Now Playing card; explanations tooltip.
  • Queue UI, crossfade, error/empty states, a11y.
  • Permissions prompts & degraded-mode banners.
  • Analytics events.

Mobile (React Native/Expo)

  • Start/stop, goal selector, likes/skip; mic/camera permissions.
  • Lightweight queue UI; background audio constraints documented.

Infra/CI

  • Feature flag mood_session_enabled.
  • Redis for candidate caching; observability dashboards.

Docs

  • README + openapi.yaml updates (new endpoints).
  • Privacy/permissions notes, troubleshooting.

Open Questions

  • Default fusion weights per modality? (propose equal weights, confidence-scaled)
  • Should Boost target both valence and energy by default, or only valence?
  • Minimum track preview length before allowing a skip to count as a negative signal?
  • Spotify SDK vs. web audio for crossfade (licensing & platform differences)?

Contributor guide