• 27-04-2025, 22:46:51
    #1
    Merhabalar CHATGPT entegresiyle ufak bir konuşma analiz sistemi ypaıyorum. Ses kaydını android veya pc den aldığımda gayet sorunsuz şekilde ses dosyası işleniyor ve dönüt alıyorum. Ama bu Iphone bana kafayı yedirtecek. Ses kaydını Iphone da alıyorum, blob çıktısı gayet güzel ve sorunsuz ama analiz et dediğimde sunucuya yüklenen ses dosyası eksik kesilmiş gibi oluyor ve analiz doğru yanıt vermiyor. Mesela ses kaydında I like eating banana and I like drinking coke diyorum, ama sunucuya yüklenen mp3 dosyasında sadece I like kısmı duruyor. Kod aşağıdaki gibi artık çıldıracağım bu apple cihazlardan çektiğmiiz ne böyle hiçbir şeye uymuyor. Yardımcı olacak arkadaşları bekliyorum
    let mediaRecorder;
    let audioChunks = [];
    let isRecording = false;
    let mimeType = '';
    
    const recordBtn = document.getElementById("recordBtn");
    const uploadBtn = document.getElementById("uploadBtn");
    const statusText = document.getElementById("status");
    const audioPlayer = document.getElementById("audioPlayer");
    const results = document.getElementById("results");
    const score = document.getElementById("score");
    const comment = document.getElementById("comment");
    const transcript = document.getElementById("transcript");
    
    let uploadedFilename = ''; // yeni değişken!
    
    recordBtn.addEventListener("click", async () => {
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        alert("Bu tarayıcı ses kaydı desteklemiyor.");
        return;
      }
    
      if (MediaRecorder.isTypeSupported('audio/webm')) {
        mimeType = 'audio/webm';
      } else if (MediaRecorder.isTypeSupported('audio/mp4')) {
        mimeType = 'audio/mp4';
      } else if (MediaRecorder.isTypeSupported('audio/mpeg')) {
        mimeType = 'audio/mpeg';
      } else {
        alert("Bu tarayıcı ses kaydı için uygun formatı desteklemiyor.");
        return;
      }
    
      if (!isRecording) {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        mediaRecorder = new MediaRecorder(stream, { mimeType });
        audioChunks = [];
    
        mediaRecorder.addEventListener("dataavailable", event => {
          audioChunks.push(event.data);
        });
    
        mediaRecorder.addEventListener("stop", () => {
          const audioBlob = new Blob(audioChunks, { type: mimeType });
          const audioUrl = URL.createObjectURL(audioBlob);
          audioPlayer.src = audioUrl;
          audioPlayer.style.display = 'block';
    
          // Ses işleniyor
          statusText.textContent = "Ses işleniyor...";
          uploadBtn.style.display = 'none';
    
          const formData = new FormData();
          formData.append("audio", audioBlob, "recording." + mimeType.split("/")[1]);
          formData.append("action", "convert");
    
          fetch("upload.php", {
            method: "POST",
            body: formData,
          })
          .then(res => res.json())
          .then(data => {
            if (data.error) throw new Error(data.error);
    
            uploadedFilename = data.filename;
            statusText.textContent = "Hazır! Şimdi analiz edebilirsin.";
            uploadBtn.disabled = false;
            uploadBtn.style.display = 'inline-block';
          })
          .catch(err => {
            alert("Ses işlenirken hata oluştu: " + err.message);
            console.error(err);
            statusText.textContent = "Hata oluştu, tekrar deneyin.";
          });
        });
    
        mediaRecorder.start();
        isRecording = true;
        recordBtn.textContent = "⏹️ Kaydı Durdur";
        statusText.textContent = "Kaydediliyor...";
      } else {
        mediaRecorder.stop();
        isRecording = false;
        recordBtn.textContent = "🔴 Kayda Başla";
        statusText.textContent = "Kayıt Durduruldu.";
      }
    });
    
    uploadBtn.addEventListener("click", () => {
      if (!uploadedFilename) {
        alert("Önce ses kaydedin.");
        return;
      }
    
      recordBtn.disabled = true;
      recordBtn.style.display = 'none';
      uploadBtn.textContent = "Analiz ediliyor...";
      uploadBtn.disabled = true;
    
      const formData = new FormData();
      formData.append("filename", uploadedFilename);
      formData.append("action", "analyze");
    
      fetch("upload.php", {
        method: "POST",
        body: formData,
      })
      .then(async (res) => {
        if (!res.ok) {
          const errText = await res.text();
          throw new Error(errText || "Sunucu hatası");
        }
        return res.json();
      })
      .then((data) => {
        if (data.error) {
          throw new Error(data.error);
        }
        score.innerHTML = `<strong>Puan:</strong> ${data.score}/100`;
        comment.innerHTML = `<strong>Dönüt:</strong><br>ing : ${data.comment_en}<br>🇹🇷: ${data.comment_tr}`;
        transcript.innerHTML = `<strong>Senin Konuşman:</strong><br>${data.transcript}`;
        results.style.display = 'block';
    
        recordBtn.disabled = false;
        recordBtn.style.display = 'inline-block';
        uploadBtn.textContent = "📤 Yükle & Analiz Et";
      })
      .catch((err) => {
        alert("Analiz sırasında hata oluştu: " + err.message);
        console.error(err);
        uploadBtn.textContent = "📤 Yükle & Analiz Et";
        uploadBtn.disabled = false;
        recordBtn.disabled = false;
        recordBtn.style.display = 'inline-block';
      });
    });
    <?php
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    
    $apiKey = APIKEY'; // kendi API anahtarın
    
    $uploadPath = __DIR__ . '/recordings/';
    if (!file_exists($uploadPath)) mkdir($uploadPath, 0777, true);
    
    if ($_POST['action'] === 'convert') {
        if (!isset($_FILES['audio'])) {
            http_response_code(400);
            echo json_encode(['error' => 'No audio uploaded']);
            exit;
        }
    
        $audio = $_FILES['audio'];
        $originalFilename = uniqid('rec_', true);
        $webmPath = $uploadPath . $originalFilename . '.webm';
        $mp3Path = $uploadPath . $originalFilename . '.mp3';
    
        move_uploaded_file($audio['tmp_name'], $webmPath);
    
        // ffmpeg ile webm → mp3 dönüştür
        $cmd = "ffmpeg -i " . escapeshellarg($webmPath) . " -vn -ar 44100 -ac 2 -b:a 192k " . escapeshellarg($mp3Path);
        exec($cmd, $output, $returnCode);
    
        if ($returnCode !== 0) {
            echo json_encode(['error' => 'FFmpeg conversion failed']);
            exit;
        }
    
        // WEBM dosyasını silebilirsin istersen
        unlink($webmPath);
    
        echo json_encode(['filename' => basename($mp3Path)]);
        exit;
    }
    
    if ($_POST['action'] === 'analyze') {
        $filename = basename($_POST['filename'] ?? '');
        if (!$filename || !file_exists($uploadPath . $filename)) {
            http_response_code(400);
            echo json_encode(['error' => 'Invalid filename']);
            exit;
        }
    
        $filepath = $uploadPath . $filename;
    
        // 1. Whisper ile yazıya çevir
        $transcriptData = openaiWhisperTranscribe($filepath, $apiKey);
        $transcript = $transcriptData['text'] ?? '';
    
        if (!$transcript) {
            echo json_encode(['error' => 'Could not transcribe audio']);
            exit;
        }
    
        // 2. GPT ile analiz
        $prompt = <<<EOT
    You are an English speaking examiner.
    
    Given this student's speech:
    "$transcript"
    
    The question they were asked is: What is your favorite meal?
    
    Please evaluate:
    - Length of the speech
    - Coherence
    - Relevance to the question
    
    Return JSON format:
    {
      "score": number (0–100),
      "comment_en": "Short feedback in English.",
      "comment_tr": "Short feedback in Turkish."
    }
    EOT;
    
        $gptResponse = openaiGPTAnalyze($prompt, $apiKey);
        $result = json_decode($gptResponse['content'] ?? '', true);
    
        if (!$result || !isset($result['score'])) {
            echo json_encode(['error' => 'AI evaluation failed']);
            exit;
        }
    
        $result['transcript'] = $transcript;
    
        header('Content-Type: application/json');
        echo json_encode($result);
        exit;
    }
    
    // --- Helper functions ---
    function openaiWhisperTranscribe($filepath, $apiKey) {
        $ch = curl_init('https://api.openai.com/v1/audio/transcriptions');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, [
            'file' => new CURLFile($filepath),
            'model' => 'whisper-1',
            'language' => 'en'
        ]);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $apiKey
        ]);
    
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
    
    function openaiGPTAnalyze($prompt, $apiKey) {
        $data = [
            "model" => "gpt-4",
            "messages" => [
                ["role" => "system", "content" => "You are an English speaking exam evaluator."],
                ["role" => "user", "content" => $prompt]
            ],
            "temperature" => 0.7
        ];
    
        $ch = curl_init('https://api.openai.com/v1/chat/completions');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey
        ]);
    
        $response = curl_exec($ch);
        curl_close($ch);
        $decoded = json_decode($response, true);
        return $decoded['choices'][0]['message'] ?? [];
    }
  • 27-04-2025, 22:52:18
    #2
    Gönderdiğiniz Kodda API Key Bulunuyor, Dikkat Etmenizi Öneririm.
  • 27-04-2025, 22:52:57
    #3
    atsizyazilim adlı üyeden alıntı: mesajı görüntüle
    Gönderdiğiniz Kodda API Key Bulunuyor, Dikkat Etmenizi Öneririm.
    Uyarınız için teşekkürler editledim