Recording and collecting audio samples

WARNING: recording audio samples requires access to the recording device of your participants. For security concerns, as of November 7, 2018, some browsers only grant access to the recording device if the script is run from a secured domain. As of November 7, 2018, the domain on which Ibex Farm was hosted did not have the credentials to identify it as secured.

This page describes the configuration you need to set up to record and collect audio samples with your IBEX project. Once you have set up your configuration, use the voiceRecorder element to let your participants record audio samples.

Sever setup

Please note that Ibex farm does NOT provide hosting for audio recordings. You need to have access to a server where you can upload a PHP file and which will authorize that PHP file to upload ZIP files to a subfolder. Free web hosting services such as Dropbox or Google drive typically do NOT offer that option. Web hosting solutions that you access via FTP/SSH (e.g., Dreamhost) would typically do the job.

  1. On your server, create a new folder dedicated to audio recording collection
  2. In that folder, create a subfolder named uploads (all lower-case, note the s at the end)
  3. Make sure that ‘owner’ has permission to write the uploads subfolder (the first digit of the numeric value/chmod should be 6 or 7, e.g. 750)
  4. In the main folder (i.e., NOT in uploads) upload a PHP file containing the following code:

<?php
// via: https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC-to-PHP/save.php
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-methods');
// Comment out the line below right after data collection
header("Access-Control-Allow-Origin: http://spellout.net");
function selfInvoker()
{
    if (!isset($_POST['fileName'])) {
        echo 'PermissionDeniedError';
        return;
    }

    $fileName = '';
    $tempName = '';

    if (isset($_POST['fileName'])) {
        $fileName = $_POST['fileName'];
        $tempName = $_FILES['file']['tmp_name'];
    }

    if (empty($fileName) || empty($tempName)) {
        echo 'PermissionDeniedError';
        return;
    }
    $filePath = 'uploads/' . $fileName;

    // make sure that one can upload only allowed zip files
    $allowed = array(
        'zip'
    );
    $extension = pathinfo($filePath, PATHINFO_EXTENSION);
    if (!$extension || empty($extension) || !in_array($extension, $allowed)) {
        echo 'PermissionDeniedError';
        continue;
    }

    if (!move_uploaded_file($tempName, $filePath)) {
        echo ('Problem saving file.');
        return;
    }

    echo ($filePath);
}
selfInvoker();
?>

Note: if your experiment is not hosted on Ibex Farm, modify the domain in the fourth line (http://spellout.net) accordingly. You can also replace it with * for the PHP script to accept upload requests from any domain, but this might not be the best idea. Read more about CORS permissions here. It is a good idea to either comment out the line or remove the PHP file from the server altogether after data collection to prevent any malicious attempt to externally upload files on your server.

For maximal security, remove the PHP file from your server as soon as your are done collecting audio recordings.

IBEX project setup

You need to make sure that the recorder knows where to upload the recordings before any VoiceRecorder command gets evaluated in your IBEX project. To this end, you should create an item with PennController.InitiateRecorder and make sure that that item is run before any instance of voiceRecorder. This is pretty simple in practice:

PennController.ResetPrefix(null);

// Indicate where to look for the PHP file you uploaded on you server
PennController.InitiateRecorder("http://my.server/myExperiment/myFile.php");

PennController(
  newText("instructions", "Please record a sample and proceed.")
      .print()
  ,
  newVoiceRecorder("recorder")
      .print()
  ,
  newButton("continue", "Click here to continue")
      .print()
      .wait()
);