diff --git a/src/components/AnnotationSettings.js b/src/components/AnnotationSettings.js
index 29ec4a843c1c2abfb4f42d4e603e3b7a5a7bf091..9e764a4cecb31945bee5b9f7486529588ef1b00e 100644
--- a/src/components/AnnotationSettings.js
+++ b/src/components/AnnotationSettings.js
@@ -1,5 +1,7 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
+import SyncIcon from '@material-ui/icons/Sync';
+import SyncDisabledIcon from '@material-ui/icons/SyncDisabled';
 import VisibilityIcon from '@material-ui/icons/VisibilitySharp';
 import VisibilityOffIcon from '@material-ui/icons/VisibilityOffSharp';
 import MiradorMenuButton from '../containers/MiradorMenuButton';
@@ -14,26 +16,45 @@ export class AnnotationSettings extends Component {
   */
   render() {
     const {
-      displayAll, displayAllDisabled, t, toggleAnnotationDisplay,
+      autoScroll, autoScrollDisabled,
+      displayAll, displayAllDisabled, t, toggleAnnotationAutoScroll, toggleAnnotationDisplay,
     } = this.props;
 
     return (
-      <MiradorMenuButton
-        aria-label={t(displayAll ? 'displayNoAnnotations' : 'highlightAllAnnotations')}
-        onClick={toggleAnnotationDisplay}
-        disabled={displayAllDisabled}
-        size="small"
-      >
-        { displayAll ? <VisibilityIcon /> : <VisibilityOffIcon /> }
-      </MiradorMenuButton>
+      <>
+        <MiradorMenuButton
+          aria-label={t(displayAll ? 'displayNoAnnotations' : 'highlightAllAnnotations')}
+          onClick={toggleAnnotationDisplay}
+          disabled={displayAllDisabled}
+          size="small"
+        >
+          { displayAll ? <VisibilityIcon /> : <VisibilityOffIcon /> }
+        </MiradorMenuButton>
+        <MiradorMenuButton
+          aria-label={autoScroll ? 'Disable auto scroll' : 'Enable auto scroll'}
+          onClick={toggleAnnotationAutoScroll}
+          disabled={autoScrollDisabled}
+          size="small"
+        >
+          { autoScroll ? <SyncIcon /> : <SyncDisabledIcon /> }
+        </MiradorMenuButton>
+      </>
     );
   }
 }
 
+AnnotationSettings.defaultProps = {
+  autoScroll: true,
+  autoScrollDisabled: true,
+  toggleAnnotationAutoScroll: () => {},
+};
 AnnotationSettings.propTypes = {
+  autoScroll: PropTypes.bool,
+  autoScrollDisabled: PropTypes.bool,
   displayAll: PropTypes.bool.isRequired,
   displayAllDisabled: PropTypes.bool.isRequired,
   t: PropTypes.func.isRequired,
+  toggleAnnotationAutoScroll: PropTypes.func,
   toggleAnnotationDisplay: PropTypes.func.isRequired,
   windowId: PropTypes.string.isRequired, // eslint-disable-line react/no-unused-prop-types
 };
diff --git a/src/components/AnnotationsOverlayVideo.js b/src/components/AnnotationsOverlayVideo.js
index 4f66399cf7f042ce7b9b851a0b86be657ab3eed5..7e1a5f436a7bb739f2454c372593380c7204b030 100755
--- a/src/components/AnnotationsOverlayVideo.js
+++ b/src/components/AnnotationsOverlayVideo.js
@@ -87,6 +87,7 @@ export class AnnotationsOverlayVideo extends Component {
     } else {
       this.temporalOffset = 0;
     }
+    this.currentTimeNearestAnnotationId = null;
 
     this.state = {
       showProgress: false,
@@ -111,13 +112,14 @@ export class AnnotationsOverlayVideo extends Component {
       hoveredAnnotationIds, selectedAnnotationId,
       highlightAllAnnotations,
       paused,
-      setCurrentTime,
-      setPaused,
+      seekToTime,
     } = this.props;
 
     this.initializeViewer();
 
+    let prevVideoPausedState;
     if (this.video) {
+      prevVideoPausedState = this.video.paused;
       if (this.video.paused && !paused) {
         const promise = this.video.play();
         if (promise !== undefined) {
@@ -126,6 +128,15 @@ export class AnnotationsOverlayVideo extends Component {
       } else if (!this.video.paused && paused) {
         this.video.pause();
       }
+      if (seekToTime !== prevProps.seekToTime) {
+        if (seekToTime !== undefined) {
+          this.seekTo(seekToTime, true);
+          return;
+        }
+      }
+      if (this.video.seeking) {
+        return;
+      }
       if (currentTime !== prevProps.currentTime) {
         if (paused && this.video.paused) {
           this.video.currentTime = currentTime - this.temporalOffset;
@@ -154,27 +165,58 @@ export class AnnotationsOverlayVideo extends Component {
 
     const selectedAnnotationsUpdated = selectedAnnotationId !== prevProps.selectedAnnotationId;
     if (selectedAnnotationsUpdated && selectedAnnotationId) {
-      setPaused(true);
-      this.video && this.video.pause();
+      if (this.currentTimeNearestAnnotationId
+        && this.currentTimeNearestAnnotationId === selectedAnnotationId) {
+        // go through
+      } else {
+        annotations.forEach((annotation) => {
+          annotation.resources.forEach((resource) => {
+            if (resource.id !== selectedAnnotationId) return;
+            if (!canvasWorld.canvasIds.includes(resource.targetId)) return;
+            if (!AnnotationsOverlayVideo.isAnnotaionInTemporalSegment(resource, currentTime)) {
+              const temporalfragment = resource.temporalfragmentSelector;
+              if (temporalfragment && temporalfragment.length > 0 && this.video) {
+                const seekto = temporalfragment[0] || 0;
+                this.seekTo(seekto, !prevVideoPausedState);
+              }
+            }
+          });
+        });
+      }
+    }
+
+    // auto scroll
+    if (this.video && !this.video.paused) {
+      let minElapsedTimeAfterStart = Number.MAX_VALUE;
+      let candidateAnnotation;
       annotations.forEach((annotation) => {
         annotation.resources.forEach((resource) => {
-          if (resource.id !== selectedAnnotationId) return;
           if (!canvasWorld.canvasIds.includes(resource.targetId)) return;
-          if (!AnnotationsOverlayVideo.isAnnotaionInTemporalSegment(resource, currentTime)) {
+          if (AnnotationsOverlayVideo.isAnnotaionInTemporalSegment(resource, currentTime)) {
             const temporalfragment = resource.temporalfragmentSelector;
             if (temporalfragment && temporalfragment.length > 0 && this.video) {
               const seekto = temporalfragment[0] || 0;
-              setPaused(true);
-              this.video.pause();
-              setCurrentTime(seekto);
-              const videoTime = seekto - this.temporalOffset;
-              if (videoTime >= 0) {
-                this.video.currentTime = videoTime;
+              const elapsedTimeAfterStart = currentTime - seekto;
+              if (elapsedTimeAfterStart >= 0 && elapsedTimeAfterStart < minElapsedTimeAfterStart) {
+                minElapsedTimeAfterStart = elapsedTimeAfterStart;
+                candidateAnnotation = resource.resource;
               }
             }
           }
         });
       });
+      if (candidateAnnotation) {
+        if (candidateAnnotation.id !== prevProps.selectedAnnotationId) {
+          const {
+            selectAnnotation,
+            windowId,
+          } = this.props;
+          if (selectedAnnotationId !== candidateAnnotation.id) {
+            selectAnnotation(windowId, candidateAnnotation.id);
+          }
+          this.currentTimeNearestAnnotationId = candidateAnnotation.id;
+        }
+      }
     }
 
     const redrawAnnotations = drawAnnotations !== prevProps.drawAnnotations
@@ -230,17 +272,12 @@ export class AnnotationsOverlayVideo extends Component {
   /** */
   onVideoPlaying(event) {
     if (this.video && this.video.currentTime !== 0) {
-      const { currentTime } = this.props;
+      const { currentTime, seekToTime } = this.props;
       const currentTimeToVideoTime = currentTime - this.temporalOffset;
       const diff = Math.abs(currentTimeToVideoTime - this.video.currentTime);
       const acceptableDiff = 1; // sec.
-      if (diff > acceptableDiff) {
-        const { setCurrentTime, setPaused } = this.props;
-        // In the flow of pausing, adjusting currentTime, and resuming playback,
-        // it is necessary to handle cases where the user explicitly pauses playback.
-        setPaused(true);
-        setCurrentTime(this.video.currentTime + this.temporalOffset); // rewind time
-        setPaused(false);
+      if (diff > acceptableDiff && seekToTime === undefined) {
+        this.seekTo(this.video.currentTime + this.temporalOffset, true);
       }
     }
     this.setState({ showProgress: false });
@@ -397,6 +434,19 @@ export class AnnotationsOverlayVideo extends Component {
     return imageSource;
   }
 
+  /** @private */
+  seekTo(seekTo, resume) {
+    const { setCurrentTime, setPaused } = this.props;
+    setPaused(true);
+    setCurrentTime(seekTo);
+    this.video.addEventListener('seeked', function seeked(event) {
+      event.currentTarget.removeEventListener(event.type, seeked);
+      if (resume) {
+        setPaused(false);
+      }
+    });
+  }
+
   /** @private */
   isCanvasSizeSpecified() {
     const { canvas, canvasWorld } = this.props;
@@ -600,6 +650,7 @@ AnnotationsOverlayVideo.defaultProps = {
   palette: {},
   paused: true,
   searchAnnotations: [],
+  seekToTime: undefined,
   selectAnnotation: () => {},
   selectedAnnotationId: undefined,
   setCurrentTime: () => {},
@@ -621,6 +672,7 @@ AnnotationsOverlayVideo.propTypes = {
   palette: PropTypes.object, // eslint-disable-line react/forbid-prop-types
   paused: PropTypes.bool,
   searchAnnotations: PropTypes.arrayOf(PropTypes.object),
+  seekToTime: PropTypes.number,
   selectAnnotation: PropTypes.func,
   selectedAnnotationId: PropTypes.string,
   setCurrentTime: PropTypes.func,
diff --git a/src/components/CanvasAnnotations.js b/src/components/CanvasAnnotations.js
index 137a4ef0bcf3f1ed42a78e90ef5df08073752b2e..2a7efadb5f40abefeceecbe00d4874843c76c88a 100644
--- a/src/components/CanvasAnnotations.js
+++ b/src/components/CanvasAnnotations.js
@@ -58,7 +58,7 @@ export class CanvasAnnotations extends Component {
   */
   render() {
     const {
-      annotations, classes, index, label, selectedAnnotationId, t, totalSize,
+      annotations, autoScroll, classes, index, label, selectedAnnotationId, t, totalSize,
       listContainerComponent, htmlSanitizationRuleSet, hoveredAnnotationIds,
       containerRef,
     } = this.props;
@@ -76,7 +76,7 @@ export class CanvasAnnotations extends Component {
                 containerRef={containerRef}
                 key={`${annotation.id}-scroll`}
                 offsetTop={96} // offset for the height of the form above
-                scrollTo={selectedAnnotationId === annotation.id}
+                scrollTo={autoScroll ? (selectedAnnotationId === annotation.id) : false}
               >
                 <MenuItem
                   button
@@ -126,6 +126,7 @@ CanvasAnnotations.propTypes = {
       id: PropTypes.string.isRequired,
     }),
   ),
+  autoScroll: PropTypes.bool,
   classes: PropTypes.objectOf(PropTypes.string),
   containerRef: PropTypes.oneOfType([
     PropTypes.func,
@@ -146,6 +147,7 @@ CanvasAnnotations.propTypes = {
 };
 CanvasAnnotations.defaultProps = {
   annotations: [],
+  autoScroll: true,
   classes: {},
   containerRef: undefined,
   hoveredAnnotationIds: [],
diff --git a/src/components/VideoViewer.js b/src/components/VideoViewer.js
index 4c285507f1299632e70de74ea473c1b238f7d51d..d13ebbdafd40db0370f8fd8b840960ce6e03cdaf 100644
--- a/src/components/VideoViewer.js
+++ b/src/components/VideoViewer.js
@@ -19,11 +19,28 @@ export class VideoViewer extends Component {
     };
   }
 
+  /** */
+  componentDidMount() {
+    const { annotations, setHasTextTrack, setPaused } = this.props;
+    setPaused(true);
+    const vttContent = flatten(
+      flattenDeep([
+        annotations.map(annotation => annotation.resources.map(
+          resources_ => resources_.resource,
+        )),
+      ]).filter(resource => resource.body && resource.body[0] && resource.body[0].format === 'text/vtt'),
+    );
+    if (vttContent && vttContent.length > 0) {
+      setHasTextTrack(true);
+    }
+  }
+
   /** */
   componentDidUpdate(prevProps) {
     const {
       canvas, currentTime, muted, paused,
       setCurrentTime, setPaused,
+      textTrackDisabled,
     } = this.props;
 
     if (paused !== prevProps.paused) {
@@ -51,9 +68,20 @@ export class VideoViewer extends Component {
       if (video.muted !== muted) {
         video.muted = muted;
       }
+      if (video.textTracks && video.textTracks.length > 0) {
+        const newMode = textTrackDisabled ? 'hidden' : 'showing';
+        if (video.textTracks[0].mode !== newMode) {
+          video.textTracks[0].mode = newMode;
+        }
+      }
     }
   }
 
+  /** */
+  componentWillUnmount() {
+    this.timerStop();
+  }
+
   /** */
   timerStart() {
     const { currentTime } = this.props;
@@ -85,7 +113,7 @@ export class VideoViewer extends Component {
   /** */
   render() {
     const {
-      canvas, classes, currentTime, videoOptions, windowId,
+      annotations, canvas, classes, currentTime, videoOptions, windowId,
     } = this.props;
 
     const videoResources = flatten(
@@ -107,13 +135,26 @@ export class VideoViewer extends Component {
         }),
       ]).filter((resource) => resource.body && resource.body[0].__jsonld && resource.body[0].__jsonld.type === 'Video'),
     );
+    const vttContent = flatten(
+      flattenDeep([
+        annotations.map(annotation => annotation.resources.map(
+          resources_ => resources_.resource,
+        )),
+      ]).filter(resource => resource.body && resource.body[0] && resource.body[0].format === 'text/vtt'),
+    );
+
     // Only one video can be displayed at a time in this implementation.
     const len = videoResources.length;
     const video = len > 0
       ? videoResources[len - 1].body[0] : null;
     const videoTargetTemporalfragment = len > 0
       ? videoResources[len - 1].temporalfragment : [];
-
+    let caption = null;
+    if (vttContent && vttContent.length > 0) {
+      caption = {
+        id: vttContent[0].body[0].id,
+      };
+    }
     return (
       <div className={classes.flexContainer}>
         <div className={classes.flexFill}>
@@ -121,6 +162,9 @@ export class VideoViewer extends Component {
             <>
               <video className={classes.video} key={video.id} ref={this.videoRef} {...videoOptions}>
                 <source src={video.id} type={video.getFormat()} />
+                { caption && (
+                  <track src={caption.id} />
+                )}
               </video>
               <AnnotationsOverlayVideo windowId={windowId} videoRef={this.videoRef} videoTarget={videoTargetTemporalfragment} key={`${windowId} ${video.id}`} />
             </>
@@ -134,23 +178,29 @@ export class VideoViewer extends Component {
 }
 
 VideoViewer.propTypes = {
+  annotations: PropTypes.arrayOf(PropTypes.object),
   canvas: PropTypes.object, // eslint-disable-line react/forbid-prop-types
   classes: PropTypes.objectOf(PropTypes.string).isRequired,
   currentTime: PropTypes.number,
   muted: PropTypes.bool,
   paused: PropTypes.bool,
   setCurrentTime: PropTypes.func,
+  setHasTextTrack: PropTypes.func,
   setPaused: PropTypes.func,
+  textTrackDisabled: PropTypes.bool,
   videoOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types
   windowId: PropTypes.string.isRequired,
 };
 
 VideoViewer.defaultProps = {
+  annotations: [],
   canvas: {},
   currentTime: 0,
   muted: false,
   paused: true,
   setCurrentTime: () => {},
+  setHasTextTrack: () => {},
   setPaused: () => {},
+  textTrackDisabled: true,
   videoOptions: {},
 };
diff --git a/src/components/ViewerNavigationVideo.js b/src/components/ViewerNavigationVideo.js
index 47355af9c80df2f4e3ff646088a156b58523f7dc..0542fe7f61f93d3e123ecf01bcfc6dfa97853c62 100755
--- a/src/components/ViewerNavigationVideo.js
+++ b/src/components/ViewerNavigationVideo.js
@@ -1,3 +1,5 @@
+import ClosedCaption from '@material-ui/icons/ClosedCaption';
+import ClosedCaptionOutlined from '@material-ui/icons/ClosedCaptionOutlined';
 import React, { Component } from 'react';
 import PauseRoundedIcon from '@material-ui/icons/PauseRounded';
 import PlayArrowRoundedIcon from '@material-ui/icons/PlayArrowRounded';
@@ -19,13 +21,9 @@ export class ViewerNavigationVideo extends Component {
 
   /** */
   handleChange = (event, newValue) => {
-    const { paused, setCurrentTime, setPaused } = this.props;
+    const { paused, setCurrentTime, setSeekTo } = this.props;
     if (!paused) {
-      // In the flow of pausing, adjusting currentTime, and resuming playback,
-      // it is necessary to handle cases where the user explicitly pauses playback.
-      setPaused(true);
-      setCurrentTime(newValue);
-      setPaused(false);
+      setSeekTo(newValue);
     } else {
       setCurrentTime(newValue);
     }
@@ -39,10 +37,13 @@ export class ViewerNavigationVideo extends Component {
       classes,
       currentTime,
       duration,
+      hasTextTrack,
       muted,
       paused,
       setMuted,
       setPaused,
+      setTextTrackDisabled,
+      textTrackDisabled,
     } = this.props;
 
     const start = (duration > 3600 || duration === undefined) ? 11 : 14;
@@ -79,6 +80,15 @@ export class ViewerNavigationVideo extends Component {
         >
           { muted ? <VolumeOffIcon /> : <VolumeUpIcon /> }
         </MiradorMenuButton>
+        { hasTextTrack && (
+          <MiradorMenuButton
+            aria-label={textTrackDisabled ? 'CC show' : 'CC hide'}
+            className={textTrackDisabled ? ns('next-canvas-button') : ns('next-canvas-button')}
+            onClick={() => { setTextTrackDisabled(!textTrackDisabled); }}
+          >
+            { textTrackDisabled ? <ClosedCaptionOutlined /> : <ClosedCaption /> }
+          </MiradorMenuButton>
+        )}
         <span className={classes.divider} />
       </div>
     );
@@ -89,19 +99,27 @@ ViewerNavigationVideo.propTypes = {
   classes: PropTypes.objectOf(PropTypes.string).isRequired,
   currentTime: PropTypes.number,
   duration: PropTypes.number,
+  hasTextTrack: PropTypes.bool,
   muted: PropTypes.bool,
   paused: PropTypes.bool,
   setCurrentTime: PropTypes.func,
   setMuted: PropTypes.func,
   setPaused: PropTypes.func,
+  setSeekTo: PropTypes.func,
+  setTextTrackDisabled: PropTypes.func,
+  textTrackDisabled: PropTypes.bool,
 };
 
 ViewerNavigationVideo.defaultProps = {
   currentTime: 0,
   duration: undefined,
+  hasTextTrack: false,
   muted: false,
   paused: true,
   setCurrentTime: () => {},
   setMuted: () => {},
   setPaused: () => {},
+  setSeekTo: () => {},
+  setTextTrackDisabled: () => {},
+  textTrackDisabled: true,
 };
diff --git a/src/config/settings.js b/src/config/settings.js
index 50e2bc752798c25001332572c1e6826c66260dab..e2b1025f094c76488a83d3334d294ad1e205be00 100644
--- a/src/config/settings.js
+++ b/src/config/settings.js
@@ -360,7 +360,7 @@ export default {
     crossOrigin: 'anonymous',
   },
   videoOptions: { // Additional props passed to <audio> element
-    controls: true,
+    controls: false,
     crossOrigin: 'anonymous',
   },
   auth: {
diff --git a/src/containers/AnnotationSettings.js b/src/containers/AnnotationSettings.js
index 1c1dd8d0c616100d50018ddd2e6da39bd7d27006..ff5b8ea37ca864d99facfbd321603d6124705db6 100644
--- a/src/containers/AnnotationSettings.js
+++ b/src/containers/AnnotationSettings.js
@@ -13,6 +13,8 @@ import { AnnotationSettings } from '../components/AnnotationSettings';
  * Mapping redux state to component props using connect
  */
 const mapStateToProps = (state, { windowId }) => ({
+  autoScroll: getWindow(state, { windowId }).autoScrollAnnotationList,
+  autoScrollDisabled: getAnnotationResourcesByMotivation(state, { windowId }).length < 2,
   displayAll: getWindow(state, { windowId }).highlightAllAnnotations,
   displayAllDisabled: getAnnotationResourcesByMotivation(
     state,
@@ -24,6 +26,9 @@ const mapStateToProps = (state, { windowId }) => ({
  * Mapping redux action dispatches to component props using connect
  */
 const mapDispatchToProps = (dispatch, { windowId }) => ({
+  toggleAnnotationAutoScroll: () => {
+    dispatch(actions.toggleAnnotationAutoScroll(windowId));
+  },
   toggleAnnotationDisplay: () => {
     dispatch(actions.toggleAnnotationDisplay(windowId));
   },
diff --git a/src/containers/AnnotationsOverlayVideo.js b/src/containers/AnnotationsOverlayVideo.js
index 5840561d5dedb024821da17351a371315f04539b..bc32f71b81be0fe8707c4bf8a1a9de9cf62e76bd 100755
--- a/src/containers/AnnotationsOverlayVideo.js
+++ b/src/containers/AnnotationsOverlayVideo.js
@@ -13,6 +13,7 @@ import {
   getConfig,
   getCurrentCanvas,
   getWindowCurrentTime,
+  getWindowSeekToTime,
   getWindowPausedStatus,
   getPresentAnnotationsOnSelectedCanvases,
   getSelectedAnnotationId,
@@ -39,6 +40,7 @@ const mapStateToProps = (state, { windowId }) => ({
     state,
     { windowId },
   ),
+  seekToTime: getWindowSeekToTime(state, { windowId }),
   selectedAnnotationId: getSelectedAnnotationId(state, { windowId }),
 });
 
diff --git a/src/containers/CanvasAnnotations.js b/src/containers/CanvasAnnotations.js
index 7c9caa748aa43713f8f59b1928fbf8c94a959957..cdd6caaa01507443f8b1e94c730c7a76ed3d8c51 100644
--- a/src/containers/CanvasAnnotations.js
+++ b/src/containers/CanvasAnnotations.js
@@ -9,6 +9,7 @@ import {
   getCanvasLabel,
   getSelectedAnnotationId,
   getConfig,
+  getWindow,
 } from '../state/selectors';
 import { CanvasAnnotations } from '../components/CanvasAnnotations';
 
@@ -32,6 +33,7 @@ const mapStateToProps = (state, { canvasId, windowId }) => ({
       state, { canvasId, windowId },
     ),
   ),
+  autoScroll: getWindow(state, { windowId }).autoScrollAnnotationList,
   htmlSanitizationRuleSet: getConfig(state).annotations.htmlSanitizationRuleSet,
   label: getCanvasLabel(state, {
     canvasId,
diff --git a/src/containers/VideoViewer.js b/src/containers/VideoViewer.js
index bbd148c854fb53e0ad20a9fe6734f66683af6ffe..07919ecc188d0f7173863d4b867b0fb508d3fea6 100644
--- a/src/containers/VideoViewer.js
+++ b/src/containers/VideoViewer.js
@@ -12,21 +12,26 @@ import {
   getWindowMutedStatus,
   getWindowPausedStatus,
   getWindowCurrentTime,
+  getWindowTextTrackDisabledStatus,
+  getPresentAnnotationsOnSelectedCanvases,
 } from '../state/selectors';
 
 /** */
 const mapStateToProps = (state, { windowId }) => ({
+  annotations: getPresentAnnotationsOnSelectedCanvases(state, { windowId }),
   canvas: (getCurrentCanvas(state, { windowId }) || {}),
   canvasWorld: getCurrentCanvasWorld(state, { windowId }),
   currentTime: getWindowCurrentTime(state, { windowId }),
   muted: getWindowMutedStatus(state, { windowId }),
   paused: getWindowPausedStatus(state, { windowId }),
+  textTrackDisabled: getWindowTextTrackDisabledStatus(state, { windowId }),
   videoOptions: getConfig(state).videoOptions,
 });
 
 /** */
 const mapDispatchToProps = (dispatch, { windowId }) => ({
   setCurrentTime: (...args) => dispatch(actions.setWindowCurrentTime(windowId, ...args)),
+  setHasTextTrack: (...args) => dispatch(actions.setWindowHasTextTrack(windowId, ...args)),
   setPaused: (...args) => dispatch(actions.setWindowPaused(windowId, ...args)),
 });
 
@@ -46,7 +51,7 @@ const styles = () => ({
     height: '100%',
     maxHeight: '100%',
     maxWidth: '100%',
-    'object-fit': 'scale-down',
+    'object-fit': 'contain', // 'scale-down',
     'object-position': 'left top',
     width: '100%',
   },
diff --git a/src/containers/ViewerNavigationVideo.js b/src/containers/ViewerNavigationVideo.js
index 8f411ae3e2b31b703b55cc11f87457b36b3bc8d9..5d894b0d921a2b052c8b4156c0bc0e7466a5b6e2 100755
--- a/src/containers/ViewerNavigationVideo.js
+++ b/src/containers/ViewerNavigationVideo.js
@@ -10,14 +10,18 @@ import {
   getWindowCurrentTime,
   getWindowMutedStatus,
   getWindowPausedStatus,
+  getWindowTextTrackDisabledStatus,
+  getWindowHasTextTrack,
 } from '../state/selectors';
 
 /** */
 const mapStateToProps = (state, { windowId }) => ({
   currentTime: getWindowCurrentTime(state, { windowId }),
   duration: getCurrentCanvasDuration(state, { windowId }),
+  hasTextTrack: getWindowHasTextTrack(state, { windowId }),
   muted: getWindowMutedStatus(state, { windowId }),
   paused: getWindowPausedStatus(state, { windowId }),
+  textTrackDisabled: getWindowTextTrackDisabledStatus(state, { windowId }),
 });
 
 /**
@@ -29,6 +33,10 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({
   setCurrentTime: (...args) => dispatch(actions.setWindowCurrentTime(windowId, ...args)),
   setMuted: (...args) => dispatch(actions.setWindowMuted(windowId, ...args)),
   setPaused: (...args) => dispatch(actions.setWindowPaused(windowId, ...args)),
+  setSeekTo: (...args) => dispatch(actions.setWindowSeekTo(windowId, ...args)),
+  setTextTrackDisabled: (...args) => dispatch(
+    actions.setWindowTextTrackDisabled(windowId, ...args),
+  ),
 });
 
 const styles = {
diff --git a/src/state/actions/action-types.js b/src/state/actions/action-types.js
index 9c610f53b2ddfd3b1b6af92f981d502bb143d840..f234ac6ba33667f743f19e880544af86fcc5c56a 100644
--- a/src/state/actions/action-types.js
+++ b/src/state/actions/action-types.js
@@ -13,6 +13,7 @@ const ActionTypes = {
   DESELECT_ANNOTATION: 'mirador/DESELECT_ANNOTATION',
   SELECT_ANNOTATION: 'mirador/SELECT_ANNOTATION',
   TOGGLE_ANNOTATION_DISPLAY: 'mirador/TOGGLE_ANNOTATION_DISPLAY',
+  TOGGLE_ANNOTATION_AUTOSCROLL: 'mirador/TOGGLE_ANNOTATION_AUTOSCROLL',
 
   FOCUS_WINDOW: 'mirador/FOCUS_WINDOW',
   SET_WORKSPACE_FULLSCREEN: 'mirador/SET_WORKSPACE_FULLSCREEN',
@@ -74,8 +75,11 @@ const ActionTypes = {
   HIDE_COLLECTION_DIALOG: 'mirador/HIDE_COLLECTION_DIALOG',
 
   SET_CURRENT_TIME: 'mirador/SET_CURRENT_TIME',
+  SET_SEEK_TO_TIME: 'mirador/SET_SEEK_TO_TIME',
   SET_VIDEO_PAUSED: 'mirador/SET_VIDEO_PAUSED',
   SET_VIDEO_MUTED: 'mirador/SET_VIDEO_MUTED',
+  SET_VIDEO_TEXTTRACK_DISABLED: 'mirador/SET_VIDEO_TEXTTRACK_DISABLED',
+  SET_VIDEO_HAS_TEXTTRACK: 'mirador/SET_VIDEO_HAS_TEXTTRACK',
 };
 
 export default ActionTypes;
diff --git a/src/state/actions/annotation.js b/src/state/actions/annotation.js
index 50d780d5ab71a2c403b1b5efb5203daad50440fd..cc860edef65797275aa9cee4601b2074797d7430 100644
--- a/src/state/actions/annotation.js
+++ b/src/state/actions/annotation.js
@@ -107,6 +107,18 @@ export function toggleAnnotationDisplay(windowId) {
   };
 }
 
+/**
+ * toggleAnnotationAutoScroll - action creator
+ *
+ * @param  {String} windowId
+ * @memberof ActionCreators
+ */
+export function toggleAnnotationAutoScroll(windowId) {
+  return {
+    type: ActionTypes.TOGGLE_ANNOTATION_AUTOSCROLL, windowId,
+  };
+}
+
 /**
  * toggleAnnotationDisplay - action creator
  *
diff --git a/src/state/actions/window.js b/src/state/actions/window.js
index c0e63ee91b58fa4c4b7bdfe2f60bbce7bd3c12a8..2609358ab702ca215e6f4bbbb55ebd751cbf6624 100644
--- a/src/state/actions/window.js
+++ b/src/state/actions/window.js
@@ -61,6 +61,7 @@ export function addWindow({ companionWindows, manifest, ...options }) {
     }
 
     const defaultOptions = {
+      autoScrollAnnotationList: true,
       canvasId: undefined,
       collectionIndex: 0,
       companionAreaOpen: true,
@@ -221,6 +222,17 @@ export function setWindowCurrentTime(windowId, currentTime) {
   });
 }
 
+/** */
+export function setWindowSeekTo(windowId, seekToTime) {
+  return ((dispatch) => {
+    dispatch({
+      seekToTime,
+      type: ActionTypes.SET_SEEK_TO_TIME,
+      windowId,
+    });
+  });
+}
+
 /** */
 export function setWindowPaused(windowId, paused) {
   return ((dispatch) => {
@@ -242,3 +254,25 @@ export function setWindowMuted(windowId, muted) {
     });
   });
 }
+
+/** */
+export function setWindowTextTrackDisabled(windowId, disabled) {
+  return ((dispatch) => {
+    dispatch({
+      textTrackDisabled: (disabled === undefined) ? true : disabled,
+      type: ActionTypes.SET_VIDEO_TEXTTRACK_DISABLED,
+      windowId,
+    });
+  });
+}
+
+/** */
+export function setWindowHasTextTrack(windowId, hasTextTrack) {
+  return ((dispatch) => {
+    dispatch({
+      hasTextTrack: (hasTextTrack === undefined) ? false : hasTextTrack,
+      type: ActionTypes.SET_VIDEO_HAS_TEXTTRACK,
+      windowId,
+    });
+  });
+}
diff --git a/src/state/reducers/windows.js b/src/state/reducers/windows.js
index 3734acdba81c15620e758ac5fa1819e3b81793b9..10644ee99303017d28b65dd4424237e1cc150d54 100644
--- a/src/state/reducers/windows.js
+++ b/src/state/reducers/windows.js
@@ -141,6 +141,14 @@ export const windowsReducer = (state = {}, action) => {
           highlightAllAnnotations: !state[action.windowId].highlightAllAnnotations,
         },
       };
+    case ActionTypes.TOGGLE_ANNOTATION_AUTOSCROLL:
+      return {
+        ...state,
+        [action.windowId]: {
+          ...state[action.windowId],
+          autoScrollAnnotationList: !state[action.windowId].autoScrollAnnotationList,
+        },
+      };
     case ActionTypes.IMPORT_MIRADOR_STATE:
       return action.state.windows || [];
     case ActionTypes.REQUEST_SEARCH:
@@ -177,6 +185,14 @@ export const windowsReducer = (state = {}, action) => {
           currentTime: action.currentTime,
         },
       };
+    case ActionTypes.SET_SEEK_TO_TIME:
+      return {
+        ...state,
+        [action.windowId]: {
+          ...state[action.windowId],
+          seekToTime: action.seekToTime,
+        },
+      };
     case ActionTypes.SET_VIDEO_PAUSED:
       return {
         ...state,
@@ -193,6 +209,22 @@ export const windowsReducer = (state = {}, action) => {
           muted: !!action.muted,
         },
       };
+    case ActionTypes.SET_VIDEO_TEXTTRACK_DISABLED:
+      return {
+        ...state,
+        [action.windowId]: {
+          ...state[action.windowId],
+          textTrackDisabled: !!action.textTrackDisabled,
+        },
+      };
+    case ActionTypes.SET_VIDEO_HAS_TEXTTRACK:
+      return {
+        ...state,
+        [action.windowId]: {
+          ...state[action.windowId],
+          hasTextTrack: !!action.hasTextTrack,
+        },
+      };
     default:
       return state;
   }
diff --git a/src/state/selectors/searches.js b/src/state/selectors/searches.js
index 3e541084e325e3ca41cd962cf119dc91cf15af3a..a1cac26ae0313ea64a92340df167bef478fbd961 100644
--- a/src/state/selectors/searches.js
+++ b/src/state/selectors/searches.js
@@ -69,7 +69,10 @@ export const getSearchNumTotal = createSelector(
         && result.json
         && result.json.within
     ));
-    return resultWithWithin?.json?.within?.total;
+    if (resultWithWithin && resultWithWithin.json && resultWithWithin.json.within) {
+      return resultWithWithin.json.within.total;
+    }
+    return undefined;
   },
 );
 
diff --git a/src/state/selectors/window.js b/src/state/selectors/window.js
index ebf7082a65a3965a8fa50903012a3eed6c9673b5..62a526c9d4b2d4bef455d53f0f2d7bbc82746585 100755
--- a/src/state/selectors/window.js
+++ b/src/state/selectors/window.js
@@ -12,6 +12,17 @@ export const getWindowCurrentTime = createSelector(
   },
 );
 
+export const getWindowSeekToTime = createSelector(
+  [
+    getWindow,
+  ],
+  (window) => {
+    if (!window) return undefined;
+
+    return window.seekToTime;
+  },
+);
+
 export const getWindowPausedStatus = createSelector(
   [
     getWindow,
@@ -33,3 +44,25 @@ export const getWindowMutedStatus = createSelector(
     return window.muted;
   },
 );
+
+export const getWindowTextTrackDisabledStatus = createSelector(
+  [
+    getWindow,
+  ],
+  (window) => {
+    if (!window) return undefined;
+
+    return window.textTrackDisabled;
+  },
+);
+
+export const getWindowHasTextTrack = createSelector(
+  [
+    getWindow,
+  ],
+  (window) => {
+    if (!window) return undefined;
+
+    return window.hasTextTrack;
+  },
+);