+1 vote
in SoSci Survey (dt.) by s098891 (355 points)

In meinem Fragebogen startet die Audioaufnahme (als Antwort auf ein Item) automatisch. Ich wollte verhindern, dass TeilnehmerInnen auf STOP klicken, bevor sie den Satz beenden, und deshalb gesagt, sie brauchen nichts drücken. Jetzt fehlen aber viele die Aufnahmen. Werden die Audios nur gespeichert, wenn man auf STOP drückt? Wenn ja, kann man mit einem Code das automatische STOP-drücken/Speichern der Datei nach abgelaufener Zeit bewirken?

3 Answers

0 votes
by SoSci Survey (328k points)

Im JavaScript-Code der Frage ist die Funktion stopRecording(), welche anschließend onStop() aufruft für die Übermittlung der Inhalte verantwortlich. Sie können diese auch nach einer definierten Zeit einfach aufrufen. Etwa in der "Zeit ist abgelaufen"-Funktion eines Timers.

by s098891 (355 points)
Heißt das, dass der Ton wirklich nicht aufgezeichnet wird, wenn man nicht auf Stop klickt und die Zeit einfach auslaufen lässt?
by SoSci Survey (328k points)
Aufgezeichnet wird - aber solange die Daten vom Aufnahme-Prozess (der im Browser läuft) nicht an den Server übermittelt werden, wird die Aufnahme nirgends gespeichert. Mit dem Seitenwechsel ist sie dann weg.
by s098891 (355 points)
Okay. Und was muss ich tun, um das Speichern zu automatisieren, auch ohne STOP-Drücken? Sie meinten, ich kann das 'in der "Zeit ist abgelaufen"-Funktion des Timers" machen? Was muss ich zum Html-Code des Recorders hinzufügen? Danke! :-)
by SoSci Survey (328k points)
Das kommt darauf an, wie Sie die Zeit bzw. deren Ablaufen bisher bestimmen.
by s098891 (355 points)
So sieht mein html-Code aus:

<!-- 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/muaz-khan/RecordRTC -->
<script src="../plugins/RecordRTC/RecordRTC.min.js"></script>
<script src="../plugins/RecordRTC/gumadapter.js"></script>


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

if ((webrtcDetectedVersion === null) || (webrtcDetectedVersion < webrtcMinimumVersion)) {
  alert("Ihr Browser unterstützt diese Aufnahme leider nicht.");
  throw new Error("no audio support");
}

var buttonStart = document.getElementById("btnStart");
var buttonStop = document.getElementById("btnStop");
var recordRTC;

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

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

function onStop(audioURL) {
    var recordedBlob = recordRTC.getBlob();
    // Transfer the data
    %q.id%.sendBLOB(recordedBlob);
}

function onStream(stream) {
    var options = {
        mimeType: "audio/ogg",
        audioBitsPerSecond: 128000
    };
    recordRTC = new RecordRTC(stream, options);
    // 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) {
      alert("Ihr Computer oder Ihr Browser unterstützt derzeit keine Tonaufnahme." + "\n\n" + error);
    }
    navigator.mediaDevices.getUserMedia(mediaConstraints).then(onStream).catch(onError);
};

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


window.addEventListener("load", startRecording)
window.addEventListener("load", function() {
  window.setTimeout(startRecording, 1000);
});

// -->
</script>
by SoSci Survey (328k points)
Dies sieht weitgehend nach dem Standard-Code der Fragevorlage aus. Sie schreiben oben noch "nach abgelaufener Zeit" ... was genau ist damit gemeint?

Wenn es nur darum geht, dass die Teilnehmer den "Weiter"-Knopf drücken, dann könnten Sie auch damit die Übermittlung auslösen:

SoSciTools.questionnaire.attachCheck(stopRecording);

Falls es danach gar nicht mehr weitergeht, müssten Sie noch ein SoSciTools.submitPage() im stopRecording() am Ende unterbringen.
by s098891 (355 points)
Auf jeder Seite, auf der sich ein Recorder befindet, gibt es auch einen timer. Teilnehmer müssen innerhalb von 8'' antworten. Damit sie keine Zeit verlieren, beginnt die Aufnahme automatisch. Auch das STOP oder Weiter klicken würde ihnen Zeit kosten. Es gibt nur einen Weiter Knopf, wenn man davor auf STOP klickt und wenn die Zeit noch nicht abgelaufen ist.
by SoSci Survey (328k points)
> Auf jeder Seite, auf der sich ein Recorder befindet, gibt es auch einen timer.

Dafür haben Sie sicher auch einen JavaScript-Code, oder? Dort wäre das stopRecording() zu integrieren. Posten Sie gerne Ihren Timer-Code.
by s098891 (355 points)
So sieht der timer-Code aus:

if (!isset($time5)) {
  $time5 = time();
  registerVariable('time5');  // Die Variable $time0 auch nach Ende des PHP-Codes aufbewahren
}
// Prüfung, ob die Zeit schon abgelaufen ist
// (z.B. weil der Teilnehmer die Seite neu geladen hat)
$timer = 8;  // Der Teilnehmer hat 1 Minute (60 Sekunden) Zeit zur Bearbeitung
if (time() >= $time5 + $timer) {
  goToPage('next');
}
// Die verbleibende Zeit muss auch dem JavaScript-Code bekannt gemacht werden
$remain = $time5 + $timer - time();
replace('%remain%', $remain);
by SoSci Survey (328k points)
Dies ist der PHP-Code zum Timer. Damit dieser funktioniert, gibt es noch einen JavaScript-Code?
by s098891 (355 points)
Das ist dann wohl der hier:

<script type="text/javascript">
<!--
// Funktion zur Weiterleitung
function weiter() {

  // Den Teilnehmer zur nächsten Seite weiterleiten
  SoSciTools.submitPage();
}
// Countdown anzeigen
var date0 = new Date();
var timeout = date0.getTime() + %remain% * 1000;
function updateCountdown() {
  // Zeit berechnen
  var date = new Date();
  var time = Math.ceil((timeout - date.getTime() - 50) / 1000);  // Verbleibende Zeit in Sekunden
  // Zeit anzeigen
  var out = document.getElementById("remain");
  if (!out) {
    return;
  }
  while (out.lastChild) {
    out.removeChild(out.lastChild);
  }
  var minutes = Math.floor(time / 60);
  var seconds = String(time - 60 * minutes);
  if (seconds.length < 2) seconds = "0" + seconds;
  var display = String(minutes) + ":" + seconds;
  var displayNode = document.createTextNode(display);
  out.appendChild(displayNode);
}
// Initialisierung der Weiterleitung
SoSciTools.attachEvent(window, "load", function(evt) {
  // Weiter-Knopf ausblenden (optional)
  SoSciTools.submitButtonsHide();
  // Zusätzlicher Timer für die Aktualisierung des Countdowns
  window.setInterval(updateCountdown, 1000);
  updateCountdown();
  // Timer für automatische Weiterleitung starten
  window.setTimeout(weiter, %remain% * 1000);
});
// -->
</script>
by SoSci Survey (328k points)
Sie haben hier gleich zu Beginn die folgende Funktion:

function weiter() {
  SoSciTools.submitPage();
}

Fügen Sie dort bitte vor dem submitPage() noch den Stop der Aufnahme ein:

function weiter() {
  stopRecording();
  SoSciTools.submitPage();
}
by s098891 (355 points)
Zumindest wird der stop-Knopf jetzt auch grau, kurz bevor zur nächsten Seite übergegangen wird, jedoch scheint keine Audio-Datei hochgeladen zu werden...
by SoSci Survey (328k points)
Dann blockiert der ausstehende Upload das "Weiter" offenbar nicht korrekt. Ich werde nochmal detailliert in den Quellcode sehe müssen, um das zu klären. Das wird allerdings 2-3 Tage in Anspruch nehmen.
by s098891 (355 points)
Ja, bitte!!!
by s098891 (355 points)
Gibt es schon eine Lösung für das Problem?:)
by SoSci Survey (328k points)
Jetzt schon ... ich habe sie der Leserlichkeit zuliebe oben als neue Antwort gepostet.
0 votes
by SoSci Survey (328k points)

Also ... im ersten Schritt ist es notwendig, dass das reguläre "Weiter" abgefangen wird. Dann muss die Übertragung angestoßen und anschließend das "Weiter" nochmal betätigt werden. Ergänzen Sie dafür unten in der Frage zum Audio-Recorder folgenden JavaScript-Code:

var audioSent = false;
function onSubmit() {
  // Check if already sent
  if (!audioSent) {
    stopRecording();
    return false;
  } else {
    return true;
  }
}
function onSendDone() {
  audioSent = true;
  SoSciTools.submitPage();
}
SoSciTools.questionnaire.attachCheck(onSubmit);

Sie sehen, dass hier eine Funtion onSendDone() verwendet wird. Diese müssen wir in der Funktion onStop() weiter oben im JavaScript-Code noch aufrufen. Ergänzen Sie die existierende Funktion bitte wie folgt:

function onStop(audioURL) {
    var recordedBlob = recordRTC.getBlob();
    // Transfer the data
    %q.id%.sendBLOB(recordedBlob, onSendDone);
}
by SoSci Survey (328k points)
Nun, das dürften Rechenfehler sein, die durch eine vereinfachte Trennung der Zeit in Minuten und Sekunden passieren. Aber das ist insgesamt natürlich nicht optimal...

Ich muss mir die Verbindung der automatischen Übermittlung in Verbindung mit dem Timer nochmal in Ruhe ansehen. Die beste Lösung wäre vermutlich, die Daten gar nicht über den Fragetyp zur Datenübermittlung, sondern über eine interne Variable zu lösen - eben weil Sie die Daten ja direkt mit dem "Weiter" übermitteln möchten. Allerdings wären dafür einige Modifikationen erforderlich. Deshalb werde ich mir erstmal ansehen, ob man guten Gewissens bei dem Fragetyp bleiben kann...
by s098891 (355 points)
Oje, den Fragetyp aller 50 items zu ändern wäre mir zu riskant, beginne in 10 Tagen mit der Datenerhebung mit 350 TeilnehmerInnen und hätte keine Zeit, den neu zusammen gestellten Test  davor  zu pilotieren...
by SoSci Survey (328k points)
Gut, dann sehe ich zu, dass wir eine Lösung für den bestehenden Fragetyp finden :)
by s098891 (355 points)
Vielen Dank. Bis jetzt hat sich noch nichts aufgetan?
by SoSci Survey (328k points)
Jetzt schon: https://support.soscisurvey.de/?qa=14749/audioaufnahme-wenn-stop-nicht-geklickt-wird&show=15075#a15075

Generell spricht natürlich auch nichts dagegen, selbst ein wenig mit dem JavaScript-Code zu experimentieren :)
0 votes
by SoSci Survey (328k points)

Damit das automatische Übertragen der Aufzeichnung auch mit Timer funktioniert, ist nur eine kleine Modifikation im JavaScript-Codes des Timers erforderlich:

<div id="remain"></div>
<script type="text/javascript">
<!--

var timer1;
var timer2;
function weiter() {
  window.clearTimeout(timer1);
  window.clearTimeout(timer2);
  var out = document.getElementById("remain");
  out.innerHTML = "0:00";
  onSubmit();
}
// Countdown anzeigen
var date0 = new Date();
var timeout = date0.getTime() + %remain% * 1000;
function updateCountdown() {
  // Zeit berechnen
  var date = new Date();
  var time = Math.ceil((timeout - date.getTime() - 50) / 1000);  // Verbleibende Zeit in Sekunden
  // Zeit anzeigen
  var out = document.getElementById("remain");
  if (!out) {
    return;
  }
  while (out.lastChild) {
    out.removeChild(out.lastChild);
  }
  var minutes = Math.floor(time / 60);
  var seconds = String(time - 60 * minutes);
  if (seconds.length < 2) seconds = "0" + seconds;
  var display = String(minutes) + ":" + seconds;
  var displayNode = document.createTextNode(display);
  out.appendChild(displayNode);
}
// Initialisierung der Weiterleitung
SoSciTools.attachEvent(window, "load", function(evt) {
  // Weiter-Knopf ausblenden (optional)
  SoSciTools.submitButtonsHide();
  // Zusätzlicher Timer für die Aktualisierung des Countdowns
  timer1 = window.setInterval(updateCountdown, 1000);
  updateCountdown();
  // Timer für automatische Weiterleitung starten
  timer2 = window.setTimeout(weiter, %remain% * 1000);
});
// -->
</script>

Hier wurde v.a die Funktion weiter() geändert, welche zum einen die Timer stoppt (damit die Anzeige nicht ins negative läuft) und zum anderen die Funktion onSubmit() aufruft, welche wir ja bereits im Audio-Recorder definiert hatten. Diese kümmert sich um Übertragung und Weiterleitung.

Hier der Vollständigkeit halber nochmal der modifizierte Code aus der Audio-Recorder-Frage.

<!-- 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/muaz-khan/RecordRTC -->
<script src="../plugins/RecordRTC/RecordRTC.min.js"></script>
<script src="../plugins/RecordRTC/gumadapter.js"></script>


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

if ((webrtcDetectedVersion === null) || (webrtcDetectedVersion < webrtcMinimumVersion)) {
  alert("Ihr Browser unterstützt diese Aufnahme leider nicht.");
  throw new Error("no audio support");
}

var buttonStart = document.getElementById("btnStart");
var buttonStop = document.getElementById("btnStop");
var recordRTC;

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

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

function onStop(audioURL) {
    var recordedBlob = recordRTC.getBlob();
    // Transfer the data
    %q.id%.sendBLOB(recordedBlob, onSendDone);
}

function onStream(stream) {
    var options = {
        mimeType: "audio/ogg",
        audioBitsPerSecond: 128000
    };
    recordRTC = new RecordRTC(stream, options);
    // 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) {
      alert("Ihr Computer oder Ihr Browser unterstützt derzeit keine Tonaufnahme." + "\n\n" + error);
    }
    navigator.mediaDevices.getUserMedia(mediaConstraints).then(onStream).catch(onError);
};

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

var audioSent = false;
function onSubmit() {
console.log("OnSubmit");
  // Check if already sent
  if (!audioSent) {
    stopRecording();
    return false;
  } else {
    return true;
  }
}
function onSendDone() {
  audioSent = true;
  SoSciTools.submitPage();
}
SoSciTools.questionnaire.attachCheck(onSubmit);

// -->
</script>
by s098891 (355 points)
edited by s098891
Vielen Dank, leider geht's trotzdem nicht. Verwende ich die zwei Codes so wird Start nicht aktiviert und nach Ablauf des Timers bleibt man auf der Seite:

https://www.soscisurvey.de/speaking123/?act=wQ2anykskG8azkGKfieb7PMu


Fehlerkonsole:
spec:   {"video":false,"audio":true}
gumadapter.js:31 chrome: {"video":false,"audio":true}
index.php?i=X0XQL5I7R75P&rnd=PGYW:154 OnSubmit
RecordRTC.min.js:15 It seems that recorder is destroyed or "startRecording" is not invoked for audio recorder.
warningLog @ RecordRTC.min.js:15
stopRecording @ RecordRTC.min.js:15
stopRecording @ index.php?i=X0XQL5I7R75P&rnd=PGYW:108
onSubmit @ index.php?i=X0XQL5I7R75P&rnd=PGYW:157
weiter @ index.php?i=X0XQL5I7R75P&rnd=PGYW:198
setTimeout (async)
(anonymous) @ index.php?i=X0XQL5I7R75P&rnd=PGYW:230
load (async)
SoSciTools.attachEvent @ SoSciTools.min.js?i=1285a:60
(anonymous) @ index.php?i=X0XQL5I7R75P&rnd=PGYW:223
by SoSci Survey (328k points)
> so wird Start nicht aktiviert

Das war ja auch noch eine dritte Modifikation - gefragt in einer anderen Frage. Ich ging davon aus, dass Sie aus den obigen Codes nur die für Sie relevanten Änderungen übernehmen.

> und nach Ablauf des Timers bleibt man auf der Seite:

Das dürfte daran liegen, weil die Aufnahme nicht gestartet wurde:

> "startRecording" is not invoked for audio recorder.
by SoSci Survey (328k points)
Wenn Sie den Code posten, der nicht funktioniert - oder einen Pretest-Link direkt (!) zur betroffenen Seite, kann ich gerne noch Tipps geben. Aber bitte haben Sie Verständnis, dass wir nicht alle individuellen Lösungswünsche für Sie implementieren können. Dafür gibt es aktuell zu viele Fragen hier im Support.

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

...