This commit is contained in:
2025-09-03 11:00:46 +02:00
parent 50dba49808
commit ade2d6ef9d
2 changed files with 95 additions and 39 deletions
+1 -14
View File
@@ -15,24 +15,11 @@ const Playback = ({ route }) => {
const { project } = route.params; const { project } = route.params;
const projectId = project?.id; const projectId = project?.id;
const songIndex = project?.songIndex; const songIndex = project?.songIndex;
console.log("sonindex", songIndex);
const sunoTaskId = project?.sunoTaskId; const sunoTaskId = project?.sunoTaskId;
const { setIsLoading } = useMinuit(); const { setIsLoading } = useMinuit();
// console.log("musicTimestamps avec songIndex:", {
// // Accès avec la clé dot notation
// musicTimeStamps: project?.[`musicTimestamps.${songIndex}`],
// // Toutes les clés qui commencent par musicTimestamps
// });
const onPressRecord = useCallback(async () => { const onPressRecord = useCallback(async () => {
try { try {
console.log(
"project",
songIndex,
"project id",
projectId,
"sunoTaskId",
sunoTaskId
);
if (!projectId || songIndex === undefined || !sunoTaskId) { if (!projectId || songIndex === undefined || !sunoTaskId) {
return; return;
// return navigate(Routes.RecordPlayback, { project }); // return navigate(Routes.RecordPlayback, { project });
+94 -25
View File
@@ -1,7 +1,13 @@
import { useFocusEffect } from "@react-navigation/native"; import { useFocusEffect } from "@react-navigation/native";
import { useAudioPlayer } from "expo-audio"; import { useAudioPlayer } from "expo-audio";
import { CameraView, useCameraPermissions } from "expo-camera"; import { CameraView, useCameraPermissions } from "expo-camera";
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import Svg, { Circle } from "react-native-svg"; import Svg, { Circle } from "react-native-svg";
@@ -14,20 +20,13 @@ import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts"; import { FONT_FAMILY } from "../../styles/Fonts";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
/**
* RecordPlayback — refactor robuste du compteur
*
* Correction de l'auto-start : on garde un flag countdownActiveRef pour
* empêcher l'effet de se déclencher tant que le timer n'a pas réellement démarré.
* On affiche 5→1 puis on bascule (pas de 0 visible) pour éviter le "bloqué sur 1".
*/
const TIME_BEFORE_INCREMENT_MS = 20000; // 20s const TIME_BEFORE_INCREMENT_MS = 20000; // 20s
const RecordPlayback = ({ route }) => { const RecordPlayback = ({ route }) => {
const { top, bottom } = useSafeAreaInsets(); const { top, bottom } = useSafeAreaInsets();
const { project } = route.params || {}; const { project } = route.params || {};
const projectId = project?.id;
const songIndex = project?.songIndex;
// Permissions // Permissions
const [cameraPermission, requestCameraPermission] = useCameraPermissions(); const [cameraPermission, requestCameraPermission] = useCameraPermissions();
@@ -55,6 +54,22 @@ const RecordPlayback = ({ route }) => {
const songUrl = project?.songUrl || null; const songUrl = project?.songUrl || null;
const player = useAudioPlayer(songUrl ? { uri: songUrl } : undefined); const player = useAudioPlayer(songUrl ? { uri: songUrl } : undefined);
const musicIndex = useMemo(() => {
const i = Number(songIndex);
return Number.isFinite(i) && i >= 0 ? i : 0;
}, [songIndex]);
const alignedWords = useMemo(() => {
const ts = project?.[`musicTimestamps.${songIndex}`];
null;
const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [];
return arr.map((w) => ({
word: String(w?.word ?? "").replace(/\n/g, " "),
startS: Number(w?.startS ?? 0),
endS: Number(w?.endS ?? 0),
}));
}, [project?.musicTimestamps, musicIndex]);
// console.log("alignedWords:", alignedWords);
useEffect(() => { useEffect(() => {
listenedMsRef.current = 0; listenedMsRef.current = 0;
incrementDoneRef.current = false; incrementDoneRef.current = false;
@@ -73,6 +88,19 @@ const RecordPlayback = ({ route }) => {
return () => clearInterval(id); return () => clearInterval(id);
}, [player]); }, [player]);
// Compute current word index from playback time
const currentTimeS = (progressInfo?.pos || 0) / 1000;
const currentIdx = useMemo(() => {
if (!alignedWords || alignedWords.length === 0) return -1;
for (let i = 0; i < alignedWords.length; i++) {
const w = alignedWords[i];
if (currentTimeS >= w.startS && currentTimeS <= w.endS) return i;
}
if (currentTimeS > (alignedWords[alignedWords.length - 1]?.endS || 0))
return alignedWords.length - 1;
return -1;
}, [alignedWords, currentTimeS]);
// Permissions au mount + cleanup // Permissions au mount + cleanup
useEffect(() => { useEffect(() => {
(async () => { (async () => {
@@ -408,24 +436,25 @@ const RecordPlayback = ({ route }) => {
position: "absolute", position: "absolute",
left: 0, left: 0,
right: 0, right: 0,
bottom: bottom + 100, bottom: bottom + 130,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
> >
<CreateLyricsHeader <CreateLyricsHeader>
// disableBlur={Platform.OS !== "ios"} {(isRecording || showProgress) && alignedWords?.length > 0 ? (
// containerStyle={{ backgroundColor: Palette.ultraLightBlack }} <KaraokeLine words={alignedWords} currentIdx={currentIdx} />
> ) : (
<Text <Text
style={{ style={{
fontSize: 16, fontSize: 16,
color: Palette.white, color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium, fontFamily: FONT_FAMILY.InterMedium,
}} }}
> >
L'enregistrement de ta vidéo commencera lorsque tu lanceras ta L'enregistrement de ta vidéo commencera lorsque tu lanceras ta
musique, et s'arrêtera à la fin du morceau. musique, et s'arrêtera à la fin du morceau.
</Text> </Text>
)}
</CreateLyricsHeader> </CreateLyricsHeader>
</View> </View>
</View> </View>
@@ -464,3 +493,43 @@ const ProgressRing = ({ size = 50, strokeWidth = 12, progress = 0 }) => {
}; };
export default RecordPlayback; export default RecordPlayback;
// Simple karaoke line renderer
const KaraokeLine = ({ words = [], currentIdx = -1 }) => {
const windowSize = 8;
const start = Math.max(0, currentIdx - 2);
const end = Math.min(
words.length,
currentIdx >= 0 ? currentIdx + windowSize : windowSize
);
const slice = words.slice(start, end);
return (
<Text
style={{
color: Palette.white,
fontSize: 18,
lineHeight: 24,
textAlign: "center",
}}
>
{slice.map((w, i) => {
const idx = start + i;
const text = String(w.word || "").replace(/\s+/g, " ");
const isCurrent = idx === currentIdx;
return (
<Text
key={`${idx}-${text}`}
style={{
color: isCurrent ? Palette.white : "#FFFFFFAA",
fontFamily: isCurrent
? FONT_FAMILY.InterSemiBold
: FONT_FAMILY.InterMedium,
}}
>
{text + " "}
</Text>
);
})}
</Text>
);
};