Popcorn/Oral History

Matt Price

Taking Stock

  • The End is Nigh!!
  • Assignment 5: Required for everyone (!!)

Oral History Assignment

  • intellectual goal: think hard about nature of oral history, and how to use digital media effectively
  • technical goal: think more about working with non-textual media, about HTML structures, and about APIs (monsters in the deep)

What the heck is this?

  • Popcorn: media "events" framework for audio & video annotation
    • developed by Mozilla for about 5 years before it was orphaned.
    • perhaps being revivified
    • keeps track of media playback, and renders specified web content between start and end timecodes.
    • for us: turns audio file into a kind of imovie-style slideshow except that the "slides" are arbitrary web content instead of photos.
    • in particular, can include google maps, wikipeida pages, and some other types of content.

Popcorn framework

  • Library-Plugin framework
    • main library tracks media element, renders content
    • plugins generate html to feed to main
    • every "event" (or "slide") is generated by calling a plugin with a JS object as parameter. cf. line 42 of popcorn-data-from-google.js to see how this works

Plugin Structure


pop.footnote({
  start: 50,
  end: 90,
  text: "Second Footnote!",
  target: "popcorn-container"
});

Google sheets: API Power

Line 16 in js/~popcorn-data-from-google.js:


var public_spreadsheet_key = 'https://docs.google.com/spreadsheets/d/1pL_Lj62_ZcW7iawTCQ_5BQsmdynCtC8y5BCNy3k2LOM/pubhtml?gid=0&single=true';
  • uses Google JSON API, which represents each spreadsheet row as a JSON object
  • column headers as property names
  • script iterates through rows & invokes appropriate popcorn plugin for each row, w/ column values as plugin parameter properties
  • if you use some other plugin that I haven't mentioned, you may need to add a column!
  • YOU DON'T HAVE TO DO THE PROGAMMING WORK – managed for you

Tabletop: small interpreter demon


var mytables = Tabletop.init( { key: public_spreadsheet_key,
                                callback: processInfo ,
                                simpleSheet: false } );

Getting Started: First, Copy Spreadsheet

Alternative Method


var public_spreadsheet_key = 'https://docs.google.com/spreadsheets/d/1pL_Lj62_ZcW7iawTCQ_5BQsmdynCtC8y5BCNy3k2LOM/pubhtml?gid=0&single=true';
  • Replace ONLY THE PART BTWN d and /pubhtml with the spreadsheet "key" from yr new sheet

Styling Popcorn Plugins

Page-specific code is found in /css/oh-styles.css

.main-container {
    grid-template-areas: "intro popcorn" "main main";
    grid-auto-columns: 1fr;
    grid-template-rows: 50vh 1fr;
}
aside#popcorn-container {
    grid-area: popcorn;
    background-color: var(--color-highlight2);
    border: 1px solid var(--color-custom-borders);
    display: flex;
    flex-direction: row;
    overflow-y: scroll;
    overflow-x: hidden;
    flex-wrap: wrap;
    max-height: 100%;
    /* space things out! */
    justify-content: space-around;
}
aside#popcorn-container > * {
    /* default base width for plugins */
    flex-basis: var(--default-width);
    flex-shrink: 1;
    flex-grow: 1;
}


/* most of the plugins will create divs or other elements w/ class "pluginname-plugin" */
/* here's one example of styling particular plugins differently from others */
#popcorn-container figure.figure-plugin {
    /* an example of setting the figure as a bit larger than the others.  */
    flex-basis: calc(var(--default-width)*4/3);
    max-width: 100%;
}

#popcorn-container .leaflet-plugin, #popcorn-container .googlemap-plugin {
    /* make these full-width by default */
    flex-basis: 100%;
}

/* you can also use the `id` column to address *most* plugins (but not all!) */

Some thoughts

  • if you are using a video (instead of audio), you may want to make changes to the grid. e.g., you might want to put the video inside the grid, next to the annotations, and either move intro to its own row or just eliminate the intro section altogether. This would likely involve change to the HTML as well.
  • are you happy with the default display of the plugins? This design assumes that you are unlikely to have more than 2 plugins visible at the same time. If you never have more than one, you may want to set --default-width to 100%. Maybe you don't even want to use a flex container!
  • set plugin-type and plugin-instance CSS with class and id properties. In general, plugin instance containers have both a plugin-specific class pluginName-plugin and an instance-spcific id (the id property you set in a spreadsheet row).
  • notice the use of CSS variables. The syntax can sometimes feel a little heavy, but ultimately they mike life a lot easier.

Getting Started with code

Install npm & run server

cd advanced-topics-yr-name
npm install 
npm run server &

Navigate to your site

firefox localhost:8080/oral-history

use DevTools to look for errors console.png

Error Sources

  • bad spreadsheet URL
  • bad time codes etc. in spreadsheet
  • JS syntax errors in popcorn-data-from-google.js
  • JS syntax errors in index.html

Good and Less Good Annotations

Good Annotations:

  • Add context/info

    Stunde null ("hour zero") refers to the period of time directly after World War II, when the future direction and status of the old German Reich was radically undertain, and a dramatic reset of all social and political expectations seemed inevitable.

  • clarify content

    "His Holiness", that is, the Dalai Lama.

  • enhance rather than distract

Less Good Annotations:

  • are not directly tied to what's being discussed in your media file
  • pass too quickly to be comprehended in real time
  • are too cluttered to interpret

Extra fun

Seek Function


const seek = function (time) {
 document.getElementById("media").currentTime= time;
 }; 

Use in Markdown thus:

When <a href="javascript:seek(75)">Jonathan discusses the trauma of wartime (1:15)</a>, 
he uses language that clearly echos that of professional psychiatric discourse as it 
came into vogue in the 1970's. 

Styling media container in chrome

audio::-webkit-media-controls-enclosure {
    background-color: rgba(20,20,20,0.4);
    border-radius: 5px;
}
audio {
    width: 100%;
}

Your Questions/Efforts