0 votes
in SoSci Survey (dt.) by s095675 (480 points)
edited by s095675

Hallo liebes Sosci Survey Team,

für meine Erhebung möchte ich einen Audio Recorder implementieren. Die Probanden sollen 3 Minuten in den Recorder sprechen. Dafür habe ich versucht einen Timer auf der Seite einzufügen der bei Klicken des Start-Buttons zeitgleich mit der Audioaufnahme startet. Ich habe mir zwei Timer aus stackoverflow heruntergeladen. Der Timer startet jedoch nicht bei Klick des Buttons, sondern läuft einfach los, aber endet bei 0:00. Ich habe versucht den Button des Recorders im Timer Skript einzufügen - erfolglos.

Der Timer soll bei Klick des Start-Buttons ("btnStart") starten und sich bei 0:00 wiederholen. Ich habe meinen Versuch nochmal rausgenommen, damit er keinen Schaden anrichtet. Finden Sie den Fehler bzw haben Sie eine Lösung parat? Vielen Dank im Voraus!

Mich wundert es, dass es auf der unten genannten Seite funktioniert aber auf meiner Sosci Survey Seite nicht.

Link zur Umfrage: https://www.soscisurvey.de/tutorial307460/

Timer: https://jsfiddle.net/robbmj/Lzyxnaoq/2/

Code des Recorders (Standard Recorder von Soscisurvey)

<!-- Warning -->
<div id="%q.id%NoAudio" class="warning">
  <div class="content">
  Ihr Gerät und/oder Browser unterstützen derzeit keine Tonaufnahme.
  </div>
</div>

<!--[if IE]>
Der Internet Explorer unterstützt diese Aufzeichnung leider nicht.
<![endif]-->

<!-- Buttons -->
<div style="margin: 2em 0 0.5em">
  <button id="btnStart" type="button" tabindex="50">START</button>
  <button id="btnStop" type="button" tabindex="50">STOP</button>
</div>
<div style="margin: 0.5em 0" id="audioReload">Bitte laden Sie die Seite neu (<a href="javascript:SoSciTools.reloadPage()">Neu Laden</a>) und gestatten Sie der Seite Zugriff auf Ihr Audio-Gerät.</div>

<!-- Audio recorder from https://github.com/ai/audio-recorder-polyfill -->
<script src="../plugins/audio-recorder-polyfill/AudioRecorder.min.js"></script>

<script type="text/javascript">
<!--
"use strict";

var buttonStart = document.getElementById("btnStart");
var buttonStop = document.getElementById("btnStop");
var mediaRecorder;
var mediaChunks = [];

function startRecording(button) {
  if (mediaRecorder) {
    mediaRecorder.start();
    buttonStart.disabled = true;
    buttonStop.disabled = false;
  }
}

function stopRecording(button) {
  if (mediaRecorder) {
    mediaRecorder.stop();
    // You may want to change this to allow a new try (replacing the old one)
    buttonStart.disabled = false;
    buttonStop.disabled = true;
    SoSciTools.submitButtonsDisplay() 
  }
}

function onStop(audioURL) {
	var recordedBlob = new Blob(mediaChunks, { 'type' : 'audio/mpeg' });
    // Transfer the data
    %q.id%.sendBLOB(recordedBlob);
}

function onStream(stream) {
    mediaRecorder = new AudioRecorder(stream);
	mediaRecorder.addEventListener("stop", onStop);
	mediaRecorder.addEventListener("dataavailable", function(e) {
		mediaChunks.push(e.data);
    });
	// Enable the start button
    buttonStart.disabled = false;
    // Remove warning
    document.getElementById("audioReload").style.display = "none";
}

function init() {
    buttonStart.disabled = true;
    buttonStop.disabled = true;

    var mediaConstraints = {
        video: false,
        audio: true
    };

    function onError(error) {
        document.getElementById("%q.id%NoAudio").style.display = "";
    }
	
    if (navigator.mediaDevices) {
        navigator.mediaDevices.getUserMedia(mediaConstraints).then(onStream).catch(onError);
        document.getElementById("%q.id%NoAudio").style.display = "none";
    } else {
        onError();
    }
	
    
};




SoSciTools.attachEvent(window, "load", init);
SoSciTools.attachEvent(buttonStart, "click", startRecording);
SoSciTools.attachEvent(buttonStop, "click", stopRecording);
SoSciTools.submitButtonsHide()

// -->
</script>

Code des Timers

<div>Registration closes in <span id="time"></span> minutes!</div>
window.onload = function () {
    var display = document.querySelector('#time'),
        timer = new CountDownTimer(3),
        timeObj = CountDownTimer.parse(3);

    format(timeObj.minutes, timeObj.seconds);
    
    timer.onTick(format);
    
    document.querySelector('button').addEventListener('click', function () {
        timer.start();
    });
    
    function format(minutes, seconds) {
        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;
        display.textContent = minutes + ':' + seconds;
    }
};

6 Answers

0 votes
by SoSci Survey (302k points)

Sehen Sie sich bitte mal die SoSci-Anleitung zum Timer an: Timer: Countdown über mehrere Seiten

Den PHP-Teil können Sie überspringen, aber das JavaScript brauchen Sie. Im Endeffekt haben Sie zwei Timer: Einen, der nach 3 Minuten etwas tut (z.B. den Stop- und Weiter-Knopf drücken) und den anderen, der sich um die Aktualisierung der Anzeige kümmert.

Den Start des Timers koppeln sie nicht an das Ladend er Seite, sondern direkt an den Aufnahme-Knopf im Audio-Recorder (btnStart). Wenn Sie im Code des Audio-Records ein wenig suchen, sehen Sie die Stelle mit addEventListener(). Auf diesem Wege starten Sie auch den Timer.

by s095675 (480 points)
Meine Antwort darauf habe ich in einer Antwort auf die ursprüngliche Frage verfasst.
0 votes
by s095675 (480 points)

Danke Ihnen für die Antwort. Im Recorder Code finde ich bzgl addEventListener() folgende Zeilen:

> mediaRecorder.addEventListener("stop", onStop);
> 	mediaRecorder.addEventListener("dataavailable", function(e) {
> 		mediaChunks.push(e.data);

Diese sehen aber eher so aus als wären sie dazu da etwas zu stoppen. Wo genau schreibe ich die Funktion für den Button und in welchem Format sollte das addEventListener() geschrieben werden?

Oder meinen sie ich sollte diese Zeilen aus dem Timer aus dem Internet übernehmen:

document.querySelector('button').addEventListener('click', function () {
        timer.start();
    });
by SoSci Survey (302k points)
Eigentlich meinte ich diese Zeile ziemlich am Ende:

SoSciTools.attachEvent(buttonStart, "click", startRecording);

Auf demselben Weg können Sie Ihre Funktion aufrufen, welche den Timer startet. Aus der empfohlenen Anleitung müssten Sie diese beiden Zeilen in solch eine Funktion packen:

var timeLeft = %timeLeft%;  // ggf. durch die Zeitspanne ersetzen
var timeStart = new Date();

Und das hier

var timerInterval = window.setInterval(updateCountdown, 250);
updateCountdown();
0 votes
by s095675 (480 points)

Danke für die Nachricht!

Ich habe jetzt in einem Zusätzlichen HTML Block folgendes innerhalb des Timer Scripts von Sosci Survey eingefügt. :

function btn() {
var timeLeft = %timeLeft%;  // ggf. durch die Zeitspanne ersetzen
var timeStart = new Date();
var timerInterval = window.setInterval(updateCountdown, 250);
SoSciTools.attachEvent(buttonStart, "click", updateCountdown);
}

Davor steht vom ursprünglichen Skript:

// Verbleibende Zeit initialisieren
var timeLeft = %timeLeft%;
var timeStart = new Date();

Und danach geht es mit dem ursprünglichen Skript weiter mit:

// Funkton zur Aktualisierung der Anzeige und Prüfung der Zeit
function updateCountdown() {
  // Zeit berechnen
  var now = new Date();
  var timePage = Math.floor((now.getTime() - timeStart.getTime()) / 1000);  // Vergangene Zeit [Sek.]
  var remain = timeLeft - timePage;
...

Allerdings bekomme ich zwei Mal folgende Fehlermeldung angezeigt:

Warning (page 6)
For the placeholder %timeLeft% neither an input field
by prepare_input() has been created nor any content by using
replace().

Darunter in ein großer Bindestrich eingeblendet.

Ich bin mir nicht genau sicher, wo der Fehler liegt. Könnte es die Position sein, der Inhalt oder beides?

by SoSci Survey (302k points)
> For the placeholder %timeLeft% neither an input field

Wie ich schon als Kommentar hinter den Platzhalter geschrieben habe: Wenn Sie Ihn nicht mittels replace() setzen - s. Anleitung - dann müssen Sie da direkt die Zeit in Sekunden reinschreiben.
by s095675 (480 points)
Das habe ich übersehen, danke! Der Timer läuft jetzt, geht aber schon los bevor der Button gedrückt wurde.

var timeLeft = 180; steht jetzt auch doppelt drin. Soll das so sein?
by SoSci Survey (302k points)
> var timeLeft = 180; steht jetzt auch doppelt drin. Soll das so sein?

Nein - die Zeilen, die in btn() stehen dürfen sonst nirgend sein ;) Aber ich habe gerade noch einen kleinen Fehler mit der Sichtbarkeit der Variablen gesehen. Es muss so aussehen.

var timeLeft;
var timeStart;
function btn() {
  timeLeft = 180;
  timeStart = new Date();
  var timerInterval = window.setInterval(updateCountdown, 250);
  SoSciTools.attachEvent(buttonStart, "click", updateCountdown);
}
0 votes
by s095675 (480 points)

Danke für die Antwort und entschuldigen sie die späte Antwort, ich habe das leider übersehen.

Die letzte Antwort von ihnen war nicht ganz korrekt, aber nach etwas herumprobieren hat es dann doch geklappt. Leider kommt keine Benachrichtigung, wenn der Timer abgelaufen ist. ich weiß nicht wieso. Außerdem ist mein Timer nicht mehr bis 0 gelaufen sondern hat bei 1 gestoppt. Deswegen habe ich 0 auf -1 gesetzt. So zeigt er am Ende der Zeit immerhin 0:00 an aber keine Benachrichtigung. Über eine Antwort würde ich mich sehr freuen. Das ist der Code des Timers:

<!-- HTML-Element zur Anzeige der Zeit -->
<div id="timeDisplay" style="font-size: 200%; margin: 16px 0; text-align: center">–</div>
 
<script type="text/javascript">
<!--
 
// Verbleibende Zeit initialisieren
var timeLeft;
var timeStart;
 

// Funkton zur Aktualisierung der Anzeige und Prüfung der Zeit
function updateCountdown() {
  // Zeit berechnen
  var now = new Date();
  var timePage = Math.floor((now.getTime() - timeStart.getTime()) / 1000);  // Vergangene Zeit [Sek.]
  var remain = timeLeft - timePage;
 
  // Zeit abgelaufen?
  if (remain <= -1) {
    remain = -1;
    // Timer stoppen
    window.clearInterval(timerInterval);
    // Eine Meldung anzeigen (optional)
    alert("Die Zeit ist vorbei.");
    // Den Teilnehmer zur nächsten Seite weiterleiten (optional)

  }
 
  // Zeit anzeigen
  var display = document.getElementById("timeDisplay");
  if (!display) {
    return;
  }
  while (display.lastChild) {
    display.removeChild(display.lastChild);
  }
  var minutes = Math.floor(remain / 60);
  var seconds = String(remain - 60 * minutes);
  if (seconds.length < 2) {
    seconds = "0" + seconds;
  }
  var displayText = String(minutes) + ":" + seconds;
  var displayNode = document.createTextNode(displayText);
  display.appendChild(displayNode);
}
 
// Initialisierung
function btn() {
  timeLeft = 5;
  timeStart = new Date();
  var timerInterval = window.setInterval(updateCountdown, 250);
  updateCountdown();
}

  SoSciTools.attachEvent(buttonStart, "click", btn);



 
// -->
</script>
by SoSci Survey (302k points)
> Leider kommt keine Benachrichtigung, wenn der Timer abgelaufen ist.

Spontan schwer zu beurteilen... fügen Sie unter

var remain = timeLeft - timePage;

doch bitte folgende Zeile ein:

console.log(remain);

Reduzieren Sie weiterhin zum Testen die Zeit auf 5 Sekunden und posten Sie einen Pretest-Link direkt zur betroffenen Seite. Anhand der JavaScript-Konsole (https://www.soscisurvey.de/help/doku.php/de:general:browser-tools) sollte sich das Problem dann schnell finden lassen.
0 votes
by s095675 (480 points)

Danke für die schnelle Antwort! Jetzt funktioniert es.

Ich habe die von Ihnen vorgeschlagene Änderung jetzt unter remain = 0; vollzogen. Außerdem habe ich nochmal unten etwas in der btn Funktion geändert, weil in den Entwicklertools gab es sonst nach Ablauf der Zeit übersekündlich eine Fehlermeldung. Aktuell gibt es noch eine Warnung in den Entwicklertools in Google Chrome. Die Umfrage soll später ausschließlich auf iPhones laufen. Besteht die Möglichkeit, dass der Browser abstürzt, sich die Seite auf dem iPhone aufhängt oder gar die Audiodaten nicht übermittelt werden, wenn es doch auf Chrome läuft? Der Browser auf iPhones ist ja standardmäßig Safari.

<!-- HTML-Element zur Anzeige der Zeit -->
<div id="timeDisplay" style="font-size: 200%; margin: 16px 0; text-align: center">&ndash;</div>
 
<script type="text/javascript">
<!--
 
// Verbleibende Zeit initialisieren
var timeLeft;
var timeStart;
 

// Funkton zur Aktualisierung der Anzeige und Prüfung der Zeit
function updateCountdown() {
  // Zeit berechnen
  var now = new Date();
  var timePage = Math.floor((now.getTime() - timeStart.getTime()) / 1000);  // Vergangene Zeit [Sek.]
  var remain = timeLeft - timePage;

 
  // Zeit abgelaufen?
  if (remain <= 0) {
    remain = 0;
    console.log(remain);
    // Timer stoppen
    window.clearInterval(timerInterval);
    // Eine Meldung anzeigen (optional)
    alert("Die Zeit ist vorbei.");
    // Den Teilnehmer zur nächsten Seite weiterleiten (optional)

  }
 
  // Zeit anzeigen
  var display = document.getElementById("timeDisplay");
  if (!display) {
    return;
  }
  while (display.lastChild) {
    display.removeChild(display.lastChild);
  }
  var minutes = Math.floor(remain / 60);
  var seconds = String(remain - 60 * minutes);
  if (seconds.length < 2) {
    seconds = "0" + seconds;
  }
  var displayText = String(minutes) + ":" + seconds;
  var displayNode = document.createTextNode(displayText);
  display.appendChild(displayNode);
}
 
// Initialisierung
function btn() {
  timeLeft = 5;
  timeStart = new Date();
  timerInterval = window.setInterval(updateCountdown, 250);
  updateCountdown();
}
  var timerInterval ;
  SoSciTools.attachEvent(buttonStart, "click", btn);



 
// -->
</script>
by SoSci Survey (302k points)
Wie lautet die Fehlermeldung denn?
0 votes
by s095675 (480 points)

Folgendes steht in der Console:

    AudioRecorder.min.js:1 [Deprecation] The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead. (https://bit.ly/audio-worklet)
    
 start @ AudioRecorder.min.js:1
    startRecording @ ?act=DzmEDA6rXRO23PEC6PuJdbzn:107
    ?act=DzmEDA6rXRO23PEC6PuJdbzn:212 0

Und folgendes steht unter Issues:

Audit usage of navigator.userAgent, navigator.appVersion, and navigator.platform
A page or script is accessing at least one of navigator.userAgent, navigator.appVersion, and navigator.platform. Starting in Chrome 101, the amount of information available in the User Agent string will be reduced.
To fix this issue, replace the usage of navigator.userAgent, navigator.appVersion, and navigator.platform with feature detection, progressive enhancement, or migrate to navigator.userAgentData.
Note that for performance reasons, only the first access to one of the properties is shown.
1 source
index.js:1
Learn more: User-Agent String Reduction

Willkommen im Online-Support von SoSci Survey.

Hier bekommen Sie schnelle und fundierte Antworten von anderen Projektleitern und direkt von SoSci Survey.

→ Eine Frage stellen


Welcome to the SoSci Survey online support.

Simply ask a question to quickly get answers from other professionals, and directly from SoSci Survey.

→ Ask a Question

...