diff --git a/record-and-playback/slides/playback/slides/lib/popcorn-complete.min.js b/record-and-playback/slides/playback/slides/lib/popcorn-complete.min.js
old mode 100644
new mode 100755
diff --git a/record-and-playback/slides/playback/slides/lib/popcorn.altimage.js b/record-and-playback/slides/playback/slides/lib/popcorn.altimage.js
new file mode 100755
index 0000000000000000000000000000000000000000..ed2e7acb0ca961463f2110556c0fa1c022d91e8a
--- /dev/null
+++ b/record-and-playback/slides/playback/slides/lib/popcorn.altimage.js
@@ -0,0 +1,253 @@
+// PLUGIN: ALTIMAGE
+
+(function ( Popcorn ) {
+
+/**
+ * Images popcorn plug-in
+ * Shows an image element
+ * Options parameter will need a start, end, href, target and src.
+ * Start is the time that you want this plug-in to execute
+ * End is the time that you want this plug-in to stop executing
+ * href is the url of the destination of a anchor - optional
+ * Target is the id of the document element that the iframe needs to be attached to,
+ * this target element must exist on the DOM
+ * Src is the url of the image that you want to display
+ * text is the overlayed text on the image - optional
+ *
+ * @param {Object} options
+ *
+ * Example:
+   var p = Popcorn('#video')
+      .altimage({
+        start: 5, // seconds
+        end: 15, // seconds
+        href: 'http://www.drumbeat.org/',
+        src: 'http://www.drumbeat.org/sites/default/files/domain-2/drumbeat_logo.png',
+        text: 'DRUMBEAT',
+        target: 'imagediv'
+      } )
+ *
+ */
+
+  var VIDEO_OVERLAY_Z = 2000,
+      CHECK_INTERVAL_DURATION = 10;
+
+  function trackMediaElement( mediaElement ) {
+    var checkInterval = -1,
+        container = document.createElement( "div" ),
+        videoZ = getComputedStyle( mediaElement ).zIndex;
+
+    container.setAttribute( "data-popcorn-helper-container", true );
+
+    container.style.position = "absolute";
+
+    if ( !isNaN( videoZ ) ) {
+      container.style.zIndex = videoZ + 1;
+    }
+    else {
+      container.style.zIndex = VIDEO_OVERLAY_Z;
+    }
+
+    document.body.appendChild( container );
+
+    function check() {
+      var mediaRect = mediaElement.getBoundingClientRect(),
+          containerRect = container.getBoundingClientRect();
+
+      if ( containerRect.left !== mediaRect.left ) {
+        container.style.left = mediaRect.left + "px";
+      }
+      if ( containerRect.top !== mediaRect.top ) {
+        container.style.top = mediaRect.top + "px";
+      }
+    }
+
+    return {
+      element: container,
+      start: function() {
+        checkInterval = setInterval( check, CHECK_INTERVAL_DURATION );
+      },
+      stop: function() {
+        clearInterval( checkInterval );
+        checkInterval = -1;
+      },
+      destroy: function() {
+        document.body.removeChild( container );
+        if ( checkInterval !== -1 ) {
+          clearInterval( checkInterval );
+        }
+      }
+    };
+  }
+
+  Popcorn.plugin( "altimage", {
+      manifest: {
+        about: {
+          name: "Popcorn image Plugin",
+          version: "0.1",
+          author: "Scott Downe, Chad Pilkey",
+        },
+        options: {
+          start: {
+            elem: "input",
+            type: "number",
+            label: "Start"
+          },
+          end: {
+            elem: "input",
+            type: "number",
+            label: "End"
+          },
+          src: {
+            elem: "input",
+            type: "url",
+            label: "Image URL",
+            "default": "http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png"
+          },
+          href: {
+            elem: "input",
+            type: "url",
+            label: "Link",
+            "default": "http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png",
+            optional: true
+          },
+          target: "image-container",
+          text: {
+            elem: "input",
+            type: "text",
+            label: "Caption",
+            "default": "Popcorn.js",
+            optional: true
+          },
+          alt: {
+            elem: "input",
+            type: "text",
+            label: "Alt-Text",
+            optional: true
+          }
+        }
+      },
+      _setup: function( options ) {
+        var img = document.createElement( "img" ),
+            target = document.getElementById( options.target );
+
+        options.anchor = document.createElement( "a" );
+        options.anchor.style.position = "relative";
+        options.anchor.style.textDecoration = "none";
+        options.anchor.style.display = "none";
+        options.anchor.setAttribute('aria-hidden', true);
+
+        // add the widget's div to the target div.
+        // if target is <video> or <audio>, create a container and routinely 
+        // update its size/position to be that of the media
+        if ( target ) {
+          if ( [ "VIDEO", "AUDIO" ].indexOf( target.nodeName ) > -1 ) {
+            options.trackedContainer = trackMediaElement( target );
+            options.trackedContainer.element.appendChild( options.anchor );
+          }
+          else {
+            target && target.appendChild( options.anchor );
+          }          
+        }
+
+        img.addEventListener( "load", function() {
+
+          // borders look really bad, if someone wants it they can put it on their div target
+          img.style.borderStyle = "none";
+
+          options.anchor.href = options.href || options.src || "#";
+          options.anchor.target = "_blank";
+
+          var fontHeight, divText;
+
+          // these cause a slide to get distorted if slide isn't near square
+          img.style.height = target.style.height;
+          //img.style.width = target.style.width;
+          img.style.display = "block";
+          img.style.marginLeft = "auto";
+          img.style.marginRight = "auto";
+
+          options.anchor.appendChild( img );
+
+          // If display text was provided, display it:
+          if ( options.text ) {
+            fontHeight = ( img.height / 12 ) + "px";
+            divText = document.createElement( "div" );
+
+            Popcorn.extend( divText.style, {
+              color: "black",
+              fontSize: fontHeight,
+              fontWeight: "bold",
+              position: "relative",
+              textAlign: "center",
+              width: img.style.width || img.width + "px",
+              zIndex: "10"
+            });
+
+            divText.innerHTML = options.text || "";
+
+            divText.style.top = ( ( img.style.height.replace( "px", "" ) || img.height ) / 2 ) - ( divText.offsetHeight / 2 ) + "px";
+            options.anchor.insertBefore( divText, img );
+          }
+        }, false );
+
+        img.src = options.src;
+	
+        // currently the alt text that is passed is only a URI for the text file not the contents 
+        // so the contents have to be retrieved
+        if (options.alt && window.XMLHttpRequest) {
+          var txtFile = new XMLHttpRequest();
+          txtFile.open("GET", options.alt, true);
+          txtFile.onreadystatechange = function() {
+            if (txtFile.readyState === 4) {
+              if (txtFile.status === 200) {
+                img.setAttribute("alt", txtFile.responseText);
+              }
+            }
+          }
+          txtFile.send(null);
+        }
+
+        options.toString = function() {
+          var string = options.src || options._natives.manifest.options.src[ "default" ],
+              match = string.replace( /.*\//g, "" );
+          return match.length ? match : string;
+        };
+      },
+
+      /**
+       * @member image
+       * The start function will be executed when the currentTime
+       * of the video  reaches the start time provided by the
+       * options variable
+       */
+      start: function( event, options ) {
+        options.anchor.style.display = "inline";
+        //options.anchor.setAttribute('aria-hidden', false);
+        if ( options.trackedContainer ) {
+          options.trackedContainer.start();
+        }
+      },
+      /**
+       * @member image
+       * The end function will be executed when the currentTime
+       * of the video  reaches the end time provided by the
+       * options variable
+       */
+      end: function( event, options ) {
+        options.anchor.style.display = "none";
+        //options.anchor.setAttribute('aria-hidden', true);
+        if ( options.trackedContainer ) {
+          options.trackedContainer.stop();
+        }
+      },
+      _teardown: function( options ) {
+        if ( options.trackedContainer ) {
+          options.trackedContainer.destroy();
+        }
+        else if ( options.anchor.parentNode ) {
+          options.anchor.parentNode.removeChild( options.anchor );
+        }
+      }
+  });
+})( Popcorn );
diff --git a/record-and-playback/slides/playback/slides/lib/popcorn.chat-timeline.js b/record-and-playback/slides/playback/slides/lib/popcorn.chattimeline.js
similarity index 74%
rename from record-and-playback/slides/playback/slides/lib/popcorn.chat-timeline.js
rename to record-and-playback/slides/playback/slides/lib/popcorn.chattimeline.js
index b050118ca363b72a4ee1446c826f7b6311c176d9..549ae3633008e3c7fc5dfcc735c999cf2e0fd7ec 100755
--- a/record-and-playback/slides/playback/slides/lib/popcorn.chat-timeline.js
+++ b/record-and-playback/slides/playback/slides/lib/popcorn.chattimeline.js
@@ -26,23 +26,14 @@
 
   var i = 1;
 
-  Popcorn.plugin( "chat-timeline" , function( options ) {
+  Popcorn.plugin( "chattimeline" , function( options ) {
 
     var target = document.getElementById( options.target ),
         contentDiv = document.createElement( "div" ),
-        container,
         goingUp = true;
 
-    if ( target && !target.firstChild ) {
-      target.appendChild ( container = document.createElement( "div" ) );
-      container.style.width = "inherit";
-      container.style.height = "inherit";
-      container.style.overflow = "auto";
-    } else {
-      container = target.firstChild;
-    }
-
     contentDiv.style.display = "none";
+    contentDiv.setAttribute('aria-hidden', true);
     contentDiv.id = "timelineDiv" + i;
 
     //  Default to up if options.direction is non-existant or not up or down
@@ -52,15 +43,15 @@
       goingUp = false;
     }
 
-    if ( target && container ) {
+    if ( target ) {
       // if this isnt the first div added to the target div
       if( goingUp ){
         // insert the current div before the previous div inserted
-        container.insertBefore( contentDiv, container.firstChild );
+        target.insertBefore( contentDiv, target.firstChild );
       }
       else {
 
-        container.appendChild( contentDiv );
+        target.appendChild( contentDiv );
       }
 
     }
@@ -70,25 +61,26 @@
     //  Default to empty if not used
     //options.innerHTML = options.innerHTML || "";
 
-    contentDiv.innerHTML = "<span><strong>" + options.name + ":&nbsp;</strong>" + options.message + "</span>";
+    contentDiv.innerHTML = "<p><strong>" + options.name + ":</strong>" + options.message + "</p>";
 
     return {
 
       start: function( event, options ) {
         contentDiv.style.display = "block";
-
+        contentDiv.setAttribute('aria-hidden', false);
         if( options.direction === "down" ) {
-          container.scrollTop = container.scrollHeight;
+          target.scrollTop = target.scrollHeight;
         }
       },
 
       end: function( event, options ) {
         contentDiv.style.display = "none";
+        contentDiv.setAttribute('aria-hidden', true);
       },
 
       _teardown: function( options ) {
 
-        ( container && contentDiv ) && container.removeChild( contentDiv ) && !container.firstChild && target.removeChild( container );
+        ( target && contentDiv ) && target.removeChild( contentDiv ) && !target.firstChild
       }
     };
   },
diff --git a/record-and-playback/slides/playback/slides/playback.html b/record-and-playback/slides/playback/slides/playback.html
index 848d37b50ecd66b7357b658bacd63dea08f2caa3..f1b5a14a8fbcdff83f8ceec894351d562b6bb6f4 100755
--- a/record-and-playback/slides/playback/slides/playback.html
+++ b/record-and-playback/slides/playback/slides/playback.html
@@ -52,15 +52,16 @@
 	}, false);
   </script>
   <script src="lib/popcorn-custom.min.js"></script>
-  <script src="lib/popcorn.chat-timeline.js"></script>
+  <script src="lib/popcorn.chattimeline.js"></script>
+  <script src="lib/popcorn.altimage.js"></script>
 </head>
 <body>
 	<div id="playbackArea">
-		<div style="width:800px; height:650px;" id="slide"></div> 
+		<div style="width:800px; height:650px;" id="slide" aria-live="polite" role="region" aria-label="Presentation slides"></div> 
 		<audio id="audioRecording" controls > You must use an HTML5 capable browser to view this page.
 		This playback requires modern browser, please use FF, Safari, Chrome</audio>
 		<div class="chatcontainer">
-			<div id="chat"></div>			
+			<div id="chat" aria-live="polite" role="region" aria-label="Chat messages"></div>			
 		</div>
 	</div>
 	<p id="footer">Recorded with <a href="http://bigbluebutton.org/">BigBlueButton</a>.</p>
diff --git a/record-and-playback/slides/scripts/process/slides.rb b/record-and-playback/slides/scripts/process/slides.rb
index 0ff0c80fe507a48e9561af8dcfa0fae0910fbec4..b8753320ed7e659c45c916509c8439baf5ed01c4 100755
--- a/record-and-playback/slides/scripts/process/slides.rb
+++ b/record-and-playback/slides/scripts/process/slides.rb
@@ -47,13 +47,15 @@ if not FileTest.directory?(target_dir)
     
     target_pres_dir = "#{processed_pres_dir}/#{pres}"
     FileUtils.mkdir_p target_pres_dir
-
+    FileUtils.mkdir_p "#{target_pres_dir}/textfiles"
+    
     images=Dir.glob("#{pres_dir}/#{pres}.{jpg,png,gif}")
     if images.empty?
          1.upto(num_pages) do |page|
            pdf_page = "#{pres_dir}/slide-#{page}.pdf"
            BigBlueButton::Presentation.extract_page_from_pdf(page, pres_pdf, pdf_page)
            BigBlueButton::Presentation.convert_pdf_to_png(pdf_page, "#{target_pres_dir}/slide-#{page}.png")
+           FileUtils.cp("#{pres_dir}/textfiles/slide-#{page}.txt", "#{target_pres_dir}/textfiles")
          end
     else
         ext = File.extname("#{images[0]}")
diff --git a/record-and-playback/slides/scripts/publish/slides.rb b/record-and-playback/slides/scripts/publish/slides.rb
index f92d859bd07f82df556a586cf281223f22f88a54..1b7608a4685f44baafde9724be047f6776f5885d 100755
--- a/record-and-playback/slides/scripts/publish/slides.rb
+++ b/record-and-playback/slides/scripts/publish/slides.rb
@@ -93,7 +93,7 @@ if (playback == "slides")
     slides_doc = Nokogiri::XML::Builder.new do |xml|
       xml.popcorn {
         xml.timeline {
-          xml.image(:in => 0, :out => first_slide_start, :src => "logo.png", :target => "slide", :width => 200, :width => 200 )
+          xml.altimage(:in => 0, :out => first_slide_start, :src => "logo.png", :target => "slide", :width => 200, :width => 200 )
           slides_events.each do |node|
             eventname =  node['eventname']
             if eventname == "SharePresentationEvent"
@@ -103,13 +103,18 @@ if (playback == "slides")
               slide_start = (slide_timestamp.to_i - meeting_start.to_i) / 1000
               slide_number = node.xpath(".//slide")[0].text()
               slide_src = "#{presentation_url}/#{presentation_name}/slide-#{slide_number.to_i + 1}.png"
+              slide_alt = "#{presentation_url}/#{presentation_name}/textfiles/slide-#{slide_number.to_i + 1}.txt"
+              #The txt files don't seem to appear in time for this script to attach the contents to slide_alt
+              #if FileTest.exist?("#{presentation_url}/#{presentation_name}/textfiles/slide-#{slide_number.to_i + 1}.txt")
+              #  slide_alt = File.open("#{presentation_url}/#{presentation_name}/textfiles/slide-#{slide_number.to_i + 1}.txt", 'r') { |f| f.read } 
+              #end
               current_index = slides_events.index(node)
               if( current_index + 1 < slides_events.length)
                 slide_end = ( slides_events[current_index + 1]['timestamp'].to_i - meeting_start.to_i ) / 1000
               else
                 slide_end = ( meeting_end.to_i - meeting_start.to_i ) / 1000
               end
-              xml.image(:in => slide_start, :out => slide_end, :src => slide_src, :target => "slide", :width => 200, :width => 200 )
+              xml.altimage(:in => slide_start, :out => slide_end, :src => slide_src, :alt => slide_alt, :target => "slide", :width => 200, :width => 200 )
               puts "#{slide_src} : #{slide_start} -> #{slide_end}"
             end
           end
@@ -119,7 +124,7 @@ if (playback == "slides")
           chat_sender = node.xpath(".//sender")[0].text()
           chat_message =  node.xpath(".//message")[0].text()
           chat_start = (chat_timestamp.to_i - meeting_start.to_i) / 1000
-          xml.timeline(:in => chat_start, :direction => "down",  :innerHTML => "<span><strong>#{chat_sender}:</strong> #{chat_message}</span>", :target => "chat" )
+          xml.chattimeline(:in => chat_start, :direction => "down",  :name => chat_sender, :message => chat_message, :target => "chat" )
         end
       }
     end