PennController for IBEX › Forums › Support › Implementing test recording
- This topic has 5 replies, 2 voices, and was last updated 2 years, 4 months ago by Jeremy.
-
AuthorPosts
-
April 24, 2022 at 10:34 am #8099dodParticipant
Hi!
I’m coding a production experiment and I’m trying to implement a test recording. The idea is to let participants check and adjust their audio/mic quality before starting. However, I’m having a couple of problems.
– I want the participants to listen to their recording; then, decide whether to do another audio test or move on to the task. To do so, I added a newMediaRecorder as part of the
success
code block of thetest.clicked
on the ‘Record again’ button. But it doesn’t seem to work. I cannot spot any errors in the syntax, so I’m a bit lost. Is there any particular reason why it’s not working?– Ideally, I want to give participants the chance to change their settings until the audio is clear. I thought about nesting a defined number of
test.clicked
commands with success/failure (if I manage to make it work!). But I was wondering if there is a less complicated way to implement this kind of loop command.– Last minor thing – and this time I most likely made some dumb errors in the syntax. When I press the “Play” button, it doesn’t wait for the audio to be completely played before moving to the next trial.
Thank you in advance for any suggestions! And sorry if it is redundant, but I couldn’t find any post on the topic.
Here’s the code so far:
InitiateRecorder("").label("init") // Let's participants check audio quality newTrial( "audio_check" , defaultText.css({"margin-bottom":"1em"}).center() , // Instructions newText("instr-1", "Before starting..." .print() , newButton("Start").center().print().wait().remove() , clear() , // Recording test 1 newMediaRecorder("audiotest1", "audio").log().record() , newButton("done","Done").center().print().wait().remove() , getMediaRecorder("audiotest1").stop() , // Listen to the audio newText("thanksPlay","Thank you! Press PLAY to listen to the audio.").print() , newButton("Play") .callback( getMediaRecorder("audiotest1") .play() .wait("playback")) .center().print().wait() , clear() , // Record again or move on newText("testagain", "If it seems to you that the audio is not clear and/or there is too much background noise...") , newText("next", "If the audio seems clear and of good quality, press CONTINUE") , getText("testagain").print() , newButton("recordagain","Record again").center().print() .test.clicked() .success( // test 2 newMediaRecorder("audiotest2", "audio").log().record(), getButton("done").center().print().wait().remove(), getMediaRecorder("audiotest2").stop(), getText("thanksPlay").print(), newButton("play2", "Play").callback(getMediaRecorder("audiotest2").play().wait("playback")).center().print().wait(), clear(), // Record again or move on getText("testagain").print(), getButton("recordagain").center().print() .test.clicked() .success( // test 3? ) .failure(), getText("next").print() ) .failure() , // or move on getText("next").print() , newButton("Continue").center().print().wait() ) UploadRecordings("upload")
April 25, 2022 at 8:59 am #8101JeremyKeymasterHi,
Why don’t you use
.print()
on the MediaRecorder element and let participants use the interface to freely record and play back? It would save you a lot of codingRe. looping: you are already using
callback
on the Button element “Play” so that’s a command you could use (on another button) to implement a loop-like behavior too. Actually you don’t need to, and probably shouldn’t, usecallback
on the “Play” button itself, because that’s what makes the script go on without waiting for playback to finishRe.
test.clicked
: you place it immediately after creating the Button element, so of course the participant won’t have time to click the button in the 0-1ms it takes the script to move from executing thenewButton
line to executing the.test.clicked
line, and so the test will always failPutting this all together, here’s the simple way to implement your test:
newTrial( "audio_check" , defaultText.css({"text-align":"center", "margin-bottom":"1em"}).center().print() , newText("instr-1", "Before starting...") , newMediaRecorder("audiotest1", "audio") .log() .print() .wait() , newText("testagain", "If it seems to you that the audio is not clear and/or there is too much background noise...") , newText("next", "If the audio seems clear and of good quality, press CONTINUE") , newButton("Continue").center().print().wait() )
If you really want to implement a custom interface, you could do something like this:
newTrial( "audio_check" , defaultText.css({"text-align":"center", "margin-bottom":"1em"}).center().print() , defaultButton.center() , newText("instr-1", "Before starting...") , newButton("trigger", "Do a test recording") .callback( clear() , newMediaRecorder("audiotest1", "audio").log().record() , newButton("Stop").print().wait().remove() , getMediaRecorder("audiotest1").stop() , newButton("Play").print().wait().remove() , getMediaRecorder("audiotest1").play().wait("playback") , newText("If it seems to you that the audio is not clear and/or there is too much background noise...") , newText("If the audio seems clear and of good quality, press CONTINUE") , getButton("trigger").print() // Clicking this will execute the callback sequence again , getButton("Continue").print() // Print the button now: clicking it will end the trial (=validate the wait command) ) .print() , // This button will only be printed at the end of a test, // So the script won't have a chance to move past the wait command until then newButton("Continue").css("margin-top","1em").wait() )
Jeremy
April 25, 2022 at 6:14 pm #8103dodParticipantHi Jeremy, thanks for the quick reply, as always!
I didn’t think at all about the print option, to be fair. I kept the recorder hidden in the experimental trials, and now I was over-complicating things. At the moment, I don’t see any particular reason for hiding it in the audio check as well. So I’ll go for printing it, and that’s it. If I change my mind later on, I know I can start from your custom interface code (I tried it, and I see your point).
At least now I’ve learned not to use the callback on the play button 🙂
Just another naive question that might come in handy in the future. So, in a code like that with the newMediaRecorder in the loopedcallback
command, PCIbex will play and save different recordings even if the mediarecorder has the same name? I mean, at the end of the day, would I have X zip files with the same “audiotest1” from a same participant, or will they somehow be labelled sequentially?As for the
test.clicked
, my bad, there was indeed an error in the syntax. I checked previous codes, and it’s true that I had always put the test in the wait brackets of buttons/dropdowns (something like newButton(“X”).wait(getButton(“X”).test.clicked…). And at the point of course it worked. Sorry again for the silly questions – I’m still pretty new with all the coding-related stuff!Thank you
April 25, 2022 at 6:55 pm #8104JeremyKeymasterHi,
I’m pretty sure you would only get recording per MediaRecorder, only the most recent one
Your questions make perfect sense to me! But, unfortunately, PennController’s reasoning is much more blunt, it doesn’t try to understand the reasoning behind the code
Jeremy
April 26, 2022 at 3:02 am #8106dodParticipantBut it definitely serves its purpose, so far!
So, I guess the same logic applies when printing the MediaRecorder and then uploading it – the zip name I got in the results line refers only to the most recent attempt, doesn’t it?
Dod
April 26, 2022 at 12:52 pm #8108JeremyKeymasterHi Dod,
Yes, whichever method you use, one MediaRecorder element means one audio file, containing the most recent recording — you should try it out yourself though to double-check. Zip files containing recordings have non-related, unique filenames and may contain one or more recordings (because trials can contain several MediaRecorder elements, and uploads can take place after several trials too) but the audio files in the zip files are indeed named after the name of the MediaRecorder
Jeremy
-
AuthorPosts
- You must be logged in to reply to this topic.