10. Working with video
Video playback in NeuroTask.js based on the JavaScript library MediaElement.js, which provides an excellent cross-browser video player that supports both older browsers and newer ones. NeuroTask Scripting hides most of the complexities, though these are still available if you need to do things that are not supported out of the box.
Adding video to a script is straightforward, requiring just two statements:
1 setvideo('big_buck_bunny');
2 await("videoended");
This will show a video player with the movie. You should specify the name of the movie without the exentsion (e.g., write ‘big_buck_bunny’ and not ‘big_buck_bunny.mp4’).
The final statement, awaitkey("videoended") makes sure the script does not close immediately, but waits for the end of
the movie. You can also specify other events for which to wait, such as a certain time or a certain key to be pressed.
To actually show a movie, must first upload it to your account. After it will appear in the list of video files in the Quick Reference side panel on the ‘editscript’ page. The movie file should be in .mp4. It is highly recommended to also upload the same file in .webm format, so that it all browsers and platforms are supported. If you just want to run it on Chrome, you only need to provide the .mp4 format. Formats other than .mp4 and .webm are not supported (no .avi, .mkv, etc.), but you can convert any movie into the desired formats with free video conversion tools, such as Any Video Converter.
10.1 Subtitles and chapters
You can add subtitles, chapters (and a little more control) as follows:
1 var s = {
2 subtitles: "bunny_subtitles.srt",
3 chapters: "bunny_chapters.vtt"
4 }
5
6 main.addblock("center","center",100,60).setvideo('big_buck_bunny',100,100,s);
7
8 await("videoended");
First you specify all the options in an object (here called s). The two files specify the subtitles and chapters. A subtitle file is in the .srt format, which is a standard format for subtitles. A good website to create these and get more explanation about them is Subtitle Horse. Chapters are shown at the top of the screen and allow jumping through a movie, which may come in handy with instruction videos.
It is necessary to construct the block in which you show the video explicitly so there is enough room to show the subtitles. This also gives you more control over the size and location. If you specify the relative width and height of a video as 100 (percent), as in the statement above, the video will fill exactly the block it is in. You must make sure that the block has a similar shape as the video.
10.2 Advanced options
The following script illustrates some advanced options. This video starts by itself and cannot to be paused or skipped. The participant in the experiment is thus forced to see the entire video. However, as an illustration, we had added the option to skip it by clicking with the left mouse button on block b3, a so called ‘click’ event.
The waitfor ... or ... construct allows two or more events to be specified, where the first one to occur is handled and the rest is ignored. So, we we click on b3, the script is no longer waiting for the end of the movie to occur.
1 var b1, b2, b3, options, advanced_options;
2
3 main = new Box();
4
5 b1 = main.addblock("center","top",100,25)
6 .text("Testing advanced (MediaElement.js) options<br>"
7 + "This 1 min movie cannot be skipped or fast forwarded<br>"
8 + "It has to be watched entirely");
9 b2 = main.addblock("center","center",60,60);
10 b3 = main.addblock("center","bottom",100,15).button("Skip Anyway!");
11
12 var video_options = {
13 autoplay: true,
14 subtitles: "bunny_subtitles.srt"
15 },
16 advanced_options = {
17 clickToPlayPause: false,
18 features: ['volume','fullscreen'],
19 enableKeyboard: false
20 };
21
22 waitfor
23 {
24 b2.setvideo('big_buck_bunny',100,80,video_options,"bunny",advanced_options)
25 .await('videoended');
26 }
27 or
28 {
29 b3.await('click');
30 }
31
32 await(1000);
33
34 b2.clear();
35 b3.clear();
36 b1.text("This could have been an instruction video or a scene for eye-witness questions, e\
37 tc.");
Other options and advanced options are listed in the following sections.
10.3 Supported video options
The following options are supported:
1 == arguments ==
2
3 video_url url without an extension, preceded by a path within the videos directory,
4 e.g., animals/grazing_cows
5 width percentage of block size (100% is default)
6 height percentage of block size (100% is default)
7 options object with objects, see below for details
8 id id for the video/media element (default is 'videoplayer1' for first player
9 on page, and then 2, 3, ...)
10
11 == options ==
12
13 options object (all members below are optional; all paths are within the videos directory)
14
15 hasposter false by default (this is the image shown at the beginning, before playing)
16 poster path/name.jpg or .png (default is url.jpg), e.g., animals/grazing_cows_evening\
17 .jpg
18
19 autoplay false On true, start playing immediately
20
21 style 'ted', 'wmp', or 'mejs' (= default). N.B. Must be lower-case.
22 formats ['mp4','webm'] is default. Also allowed: 'ogv'. N.B. Even with one format,
23 you still need an array, e.g., ['mp4'].
1 subtitles path/name.srt, e.g., animals/cows.srt (e.g.,
2 see http://subtitle-horse.com/ for online editor)
3 chapters path/name.vtt, e.g., animals/cows_and_horses.vtt
4
5 from position where to start in ms (0 is default)
6 to position where to end in ms (-1, signals end of movie, is
7 default) (the to option is not implemented yet)
8
9
10 volume 80, initial volume (mejs uses 0.8 here; we remain conisistent with SoundManage\
11 r2)
In addition, the following advanced options are supported:
1 // if the video width is not specified, this is the default
2 defaultVideoWidth: 480,
3 // if the video height is not specified, this is the default
4 defaultVideoHeight: 270,
5 // if set, overrides video width
6 videoWidth: -1,
7 // if set, overrides video height
8 videoHeight: -1,
9 // width of audio player
10 audioWidth: 400,
11 // height of audio player
12 audioHeight: 30,
13 // initial volume when the player starts
14 startVolume: 0.8,
15 // useful for audio player loops; the mediaelement player can also play (just) audio
16 loop: false,
17 // enables Flash and Silverlight to resize to content size
18 enableAutosize: true,
19 // the order of controls you want on the control bar (and other plugins below)
20 features: ['playpause','progress','current','duration','tracks','volume','fullscreen'],
21 // Hide controls when playing and mouse is not over the video
22 alwaysShowControls: false,
23 // force iPad's native controls
24 iPadUseNativeControls: false,
25 // force iPhone's native controls
26 iPhoneUseNativeControls: false,
27 // force Android's native controls
28 AndroidUseNativeControls: false,
29 // forces the hour marker (##:00:00)
30 alwaysShowHours: false,
31 // show framecount in timecode (##:00:00:00)
32 showTimecodeFrameCount: false,
33 // used when showTimecodeFrameCount is set to true
34 framesPerSecond: 25,
35 // turns keyboard support on and off for this instance
36 enableKeyboard: true,
37 // when this player starts, it will pause other players
38 pauseOtherPlayers: true,
39 // array of keyboard commands
40 keyActions: []
10.4 Getting the video player
Once created with b.setvideo(), using the correct arguments, the video player in block b can be accessed with b.video. This allows a few additional functions to be used, such as b.video.play() and b.video.pause(). There is no stop() function because the HTML5 standard does not include this. Other properties can be found at http://mediaelementjs.com/#api. We will incorportate and document additional options later.
10.5 Showing the same video simultaneously in two blocks
For some purposes you may want to show the same video simultaneously in several blocks, e.g., left and right of a fixation point to test the distracting effect of certain moving stimuli. It is not possible to achieve absolutely simultaneous playback but you can get pretty close. The following script shows two movies, left and right, which start automatically and run to the end. There are no options for the subject to change anything about these movies: no skipping, full-screen, etc.
1 var b1, b2, b3, cover, options, advanced_options;
2
3 b1 = addblock("center","top",100,25)
4 .text("Two snakes");
5
6 b2 = addblock("left","center",30,20);
7 b3 = addblock("right","center",30,20);
8
9 // Cover player until it is playing to hide initial startup stuff
10 cover2 = addblock("left","center",32,32,"white");
11 cover3 = addblock("right","center",32,32,"white");
12
13 var video_options = {
14 autoplay: true // Start right away
15 },
16 advanced_options = {
17 clickToPlayPause: false, // Disable click
18 features: [], // No controls visible (Play etc.)
19 pauseOtherPlayers: false, // Allow two or more players
20 enableKeyboard: false // No keyboard shortcuts
21 };
22
23 b2.setvideo('animated_snake_moving_1',100,100,video_options,"snake1",advanced_options);
24 // no black background
25 query(".mejs-container",b2.node).style("background-color","white");
26 query(".mejs-controls",b2.node).style("display","none"); // Hide controls
27
28 // Make sure the second video player has a different ID, here 'snake2'
29 b3.setvideo('animated_snake_moving_1',100,100,video_options,"snake2",advanced_options);
30 query(".mejs-container",b3.node).style("background-color","white");
31 query(".mejs-controls",b3.node).style("display","none");
32
33 b3.await('videoplaying'); // Starting a video may take some time, so we wait for this
34
35 cover2.style("background-color","transparent"); // Then, we remove the cover on playing
36 cover3.style("background-color","transparent");
37
38 await("videoended"); // We finish up as soon as the first player has ended
39
40 b2.deletevideo(); // Delete the players; we will (re)create new ones all the time
41 b3.deletevideo();
42 b2.clear(); // We clear the block
43 b3.clear();
44
45 await(500);
46
47 b1.text("That's all folks!");
48
49 await(2000);
Blocks b2 and b3 show the same video, which is assumed to be available in ‘mp3’ and ‘webm’ format. Both blocks are initially covered by two white, non-transparent ‘cover’ blocks. The reason we do this here is that while the video players are loading their movie, they will show a wait cursor and may occasionally flash. This is now hidden behind the cover. Both videos will start playing nearly immediately at which point they emit the ‘videoplaying’ event. The covers are then made transparent. As soon as the videos have ended we delete the video players and clear the blocks.
The MediaElement player will show black bars if the video native size does not coincide with the specified size. We restyle these black bars to white bars, making them invisible. This done by finding the background DOM node with query(".mejs-container",b2.node) and then using the style() function on the returned DOM node. We similarly make the block with volume controls etc. invisible. Though we specifed with the features option, features: [], that no controls should be visible, some browsers still show an empty gray area for this.