CINXE.COM
SFGovTV2 LIVE (Osprey)
<!DOCTYPE html> <html lang="en"> <head> <title>SFGovTV2 LIVE (Osprey)</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Live and Recorded Public meetings of SFGovTV2 LIVE (Osprey) for City and County of San Francisco" /> <meta name="keywords" content="City and County of San Francisco, SFGovTV2 LIVE (Osprey), live, video, meeting, public, recorded, events, city, state, federal transparency, freedom of information, FOIA, agenda, minutes" /> <style type="text/css"> /** * normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css * * https://github.com/necolas/normalize.css/blob/master/LICENSE.md */ html { line-height: 1.15; -webkit-text-size-adjust: 100%; } body { margin: 0; } h1 { font-size: 2em; margin: 0.67em 0; } hr { box-sizing: content-box; height: 0; overflow: visible; } pre { font-family: monospace, monospace; font-size: 1em; } a { background-color: transparent; } abbr[title] { border-bottom: none; text-decoration: underline; text-decoration: underline dotted; } b, strong { font-weight: bolder; } code, kbd, samp { font-family: monospace, monospace; font-size: 1em; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } img { border-style: none; } button, input, optgroup, select, textarea { font-family: inherit; font-size: 100%; line-height: 1.15; margin: 0; } button, input { overflow: visible; } button, select { text-transform: none; } button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; } button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } fieldset { padding: 0.35em 0.75em 0.625em; } legend { box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; } progress { vertical-align: baseline; } textarea { overflow: auto; } [type="checkbox"], [type="radio"] { box-sizing: border-box; padding: 0; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { -webkit-appearance: textfield; outline-offset: -2px; } [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } details { display: block; } summary { display: list-item; } template { display: none; } [hidden] { display: none; } </style> <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous"> <link href="//fonts.googleapis.com/css?family=Lato:300|Open+Sans:300" rel="stylesheet"> <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <style type="text/css"> *, *:before, *:after { box-sizing: inherit; } html { font-family: 'Open Sans', sans-serif; font-size: 62.5%; font-weight: 300; font-style: normal; font-stretch: 100%; box-sizing: border-box; } html, body { height: 100vh; margin: 0; padding: 0; } h1, h2, h3, h4, h5, h6 { font-family: 'Lato', sans-serif; margin: 0; padding: 0; } h1 { line-height: 250%; } h2 { line-height: 225%; } h3 { line-height: 200%; } h4 { line-height: 175%; } h5 { line-height: 150%; } h6 { line-height: 125%; } p { margin: 0 0 15px; } p, span { font-size: 1.6rem; line-height: 2.4rem; } body > div.grid { display: -ms-grid; -ms-grid-columns: 50vw 50vw; -ms-grid-rows: fit-content(75px) auto 75px 1fr; display: grid; grid-template-columns: 50vw 50vw; grid-template-rows: fit-content(75px) auto 75px 1fr; grid-template-areas: "index-header index-documents" "index-video index-documents" "index-navigation index-documents" "index-content index-documents"; } #captions { display: none; min-height: 88px; background-color: black; padding: 5px 0; text-align: center; } .captions-line { font-weight:bold; line-height: normal; color: white; font-size: 15px; margin: 5px 0 5px 0; flex-grow: 1; display: flex; flex-direction: column; justify-content: left; } .center-center { text-align: center; line-height: 100%; } .documents-toolbar-item { display: flex; justify-content: center; align-items: center; color: white; min-width: 125px; max-width: 235px; height: 55px; font-size: 14px; line-height: 16px; letter-spacing: 1.2%; padding: 0px 15px; cursor: pointer; } .documents-toolbar-icon { margin-right: 15px; } .documents-default-document { height: 100%; background-color: #fff; } #documents-viewer-iframe { height: 100%; width: 100%; } #documents { -ms-grid-column: 1; -ms-grid-row: 1; grid-area: documents-index; overflow-y: scroll; } #download { -ms-grid-column: 1; -ms-grid-row: 4; grid-area: index-content; background-image: linear-gradient(to bottom, #2e2e30, #1f1f1f); flex-direction: column; justify-content: flex-start; align-items: center; color: white; } #download-info-desktop { display: flex; flex-direction: column; justify-content: center; margin: 25px; font-size: 15px; } .download-links { color: #848484 } #download-options { grid-area: download-options; margin: 0px 15px; display: flex; flex-wrap: wrap; justify-content: space-evenly; align-content: center; max-height: 250px; padding-top: 20px; } .download-option { text-decoration: none; margin: 30px; color: #848484; display: flex; flex-direction: column; align-items: center; justify-content: center; } .download-type { color: #D4D4D4; margin-top: 20px; } #email { color: #848484; } #embed { -ms-grid-column: 1; -ms-grid-row: 4; grid-area: index-content; background-image: linear-gradient(to bottom, #2e2e30, #1f1f1f); flex-direction: column; justify-content: flex-start; align-items: center; color: white; overflow-y: scroll; } #embed-autoplay { margin-left: 25px; } #embed-height { display: flex; justify-content: flex-start; margin: 10px; font-size: 15px; } #embed-height-input { margin-left: 10px; } #embed-info-desktop { display: flex; flex-direction: column; justify-content: center; margin: 5px; font-size: 15px; } #embed-link-desktop { margin: 10px; padding: 10px 10px 0px 10px; background-color: #e6e5e5; border-radius: 5px; color: black; min-width: 500px; } #embed-link-desktop > input { width: 95%; margin: 10px; } #embed-mobile-document { display:none; } #embed-slider-display { text-align: center; margin-top: 10px; } #embed-slider { margin-top: 10px; } #embed-width { display: flex; justify-content: flex-start; margin: 10px; font-size: 15px; } #embed-width-label { padding-right:4px; } #embed-width-input { margin-left: 10px; } #facebook, #facebook-mobile { color: #3d5a96; } .fp-captions { display: none; } /* To control display of captions on flowplayer_native you can use .fp-captions .fp-cue {} */ .flex-col-center { display: flex; flex-direction: column; justify-content: center; } #google { color: #dd4d42; } .grid { display: flex; overflow: hidden; height: 100%; } #header { min-height: 75px; -ms-grid-column: 1; -ms-grid-row: 1; grid-area: index-header; } #header h1 { line-height: 7.5rem; } #index { grid-area: index-content; -ms-grid-column: 1; -ms-grid-row: 4; overflow-y: auto; overflow-x: hidden; flex-direction: column; justify-content: flex-start; } #index .current-item { min-height: 44px; text-align: left; border-bottom: 1px solid #333333; background-color: #FFFFFF; font-size: 16px; line-height: 22px; letter-spacing: 5%; color: #000000; padding: 20px 5px 20px 30px; } #index .current-item-label { font-size: 80%; font-weight: bold; text-transform: uppercase; } .index-content { display: none; } .index-content-visible { -ms-grid-column: 1; -ms-grid-row: 4; grid-area: index-content; display: flex; } #index-documents { -ms-grid-column: 2; -ms-grid-row: 1; -ms-grid-row-span: 4; grid-area: index-documents; display: flex; flex-direction: column; justify-content: flex-start; } #index-documents-toolbar { display: flex; justify-content: flex-start; align-items: center; background-color: #30343A; min-height: 55px; } .index-point, .index-point:visited, .index-point.selected { cursor: pointer; text-align: left; border-bottom: 1px solid #333333; background-color: #FFFFFF; font-size: 16px; line-height: 22px; letter-spacing: 5%; color: #23527c; padding: 10px 15px; display: block; } .index-point:active { background-color: #F2F2F2; } .index-point:hover { text-decoration: underline; background-color: #F2F2F2; } .index-point.selected { background-color: #23527c; color: #ffffff; } /* Hide Player controls on Live Streams */ .is-live .fp-player .fp-ui .fp-controls .fp-playbtn, .is-live .fp-player .fp-ui .fp-controls .seek-backward, .is-live .fp-player .fp-ui .fp-controls .seek-forward{ display: none; } .k-widget .k-tooltip .k-slider-tooltip { display: block; position:absolute; top:50%; } #linked-in, #linked-in-mobile { color: #0077b5; } #navigation { display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: flex-start; align-items: center; margin: 0; padding: 0; min-height: 75px; max-height: 75px; background-color: #f6f6f6; border-top: 1px solid #d0d0d0; -ms-grid-column: 1; -ms-grid-row: 3; grid-area: index-navigation; } .navigation-element { align-items: center; height: 75px; font-size: 14px; line-height: 16px; letter-spacing: 1.2%; border-right: 2px solid #f2f2f2; padding: 0px 20px; display: flex; flex-grow: 1; flex-direction: column; justify-content: center; min-width: 50px; color: #23527c; cursor: pointer; text-decoration: none; background-color: inherit; } .navigation-element.selected { color: #ffffff; background-color: #23527c; } #navigation-mobile-display-agenda, #navigation-mobile-display-minutes, #navigation-mobile-display-documents { display: none; } .overflow-ellipsis { text-overflow: ellipsis; } #player-error { align-items: center; justify-content: center; background: black; min-height: 400px; color: white; display: flex; padding: 20px; text-align: center; } #player-error span { display: inline-block; font-size: 26px; line-height: 40px; } .selected-document { background-color: #484F5A; } #share { -ms-grid-column: 1; -ms-grid-row: 4; grid-area: index-content; background-image: linear-gradient(to bottom, #2e2e30, #1f1f1f); flex-direction: column; justify-content: flex-start; align-items: center; color: white; overflow-y: scroll; } #share-info-desktop { display: flex; flex-direction: column; justify-content: center; margin: 5px; font-size: 15px; } .share-info-item { margin: 5px; } .share-info-item > input { margin: 0px 5px; } #share-link-desktop { margin: 5px; padding: 5px 5px 0px 5px; background-color: #e6e5e5; border-radius: 5px; color: black; min-width: 500px; } #share-link-desktop > input { width: 95%; margin: 10px; } .share-provider { text-decoration: none; display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 20px; } #share-providers { grid-area: share-providers; margin: 0px 15px; display: flex; flex-wrap: wrap; justify-content: space-evenly; align-content: center; max-height: 250px; } .share-provider-name { color: #D4D4D4; margin-top: 20px; font-size: 15px; text-align: center; /* Fixes IE styling */ } .sliding-pane { display: none; } .sliding-pane-visible { display: block; } #twitter { color: #2aa3ef; } #video { -ms-grid-column: 1; -ms-grid-row: 2; grid-area: index-video; } #video-name { padding-left: 16px; background-color: #f8f8f8; height: 50px; text-align: left; border-bottom: 1px solid #e0e0e0; font-size: 16px; line-height: 22px; letter-spacing: 5%; color: #4F4F4F; } /* IE Hacky Stuff */ @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { } @media all and (max-width: 1023px) { body > div.grid { display: -ms-grid; -ms-grid-columns: 100%; -ms-grid-rows: 0px auto 1fr 75px; display: grid; height: 100vh; grid-template-rows: fit-content(40vh) minmax(100px, 1fr) 75px; grid-template-columns: 100%; grid-template-areas: "index-video" "index-content" "index-navigation"; max-height: 100%; } #share, #embed, #download, #index { -ms-grid-column: 1; -ms-grid-row: 3; } #share, #embed { position: relative; } #share-content, #embed-content { position: absolute; top: 0; } #content-documents .grid { -ms-grid-column: 1; -ms-grid-row: 3; grid-area: index-content; display: -ms-grid; -ms-grid-columns: 100%; -ms-grid-rows: 1fr; display: grid; grid-template-columns: 100%; grid-template-rows: 1fr; grid-template-areas: "documents-index"; width: 100%; background-color: white; } #content-index .grid { display: -ms-grid; -ms-grid-columns: 100%; -ms-grid-rows: 75px auto 1fr 75px; display: grid; height: 100vh; grid-template-columns: 100%; grid-template-rows: 75px auto minmax(100px, 1fr) 75px; grid-template-areas: "index-header" "index-video" "index-content"; max-height: 100%; } .document { display: flex; flex-direction: row; justify-content: flex-start; padding-left: 16px; border-top: 1px solid #f2f2f2; } .document-group { display: flex; flex-direction: column; justify-content: flex-start; text-decoration: none; cursor: pointer; color: #4F4F4F; } .document-icon-blue, .document-icon-gray, .document-icon-green, .document-icon-red { max-height: 42px; max-width: 42px; border-radius: 9px; background-color: #f39797; flex-grow: 1; font-size: 11px; line-height: 22px; letter-spacing: 8%; margin-top: 16.5px; color: #ffffff; } .document-icon-blue { background-color: #6fa1dd; } .document-icon-gray { background-color: #828282; } .document-icon-green { background-color: #6fcf97; } .document-label { min-height: 25px; background-color: #f5f5f5; text-align: left; padding-left: 16px; font-size: 12px; line-height: 22px; letter-spacing: 5%; } .document-text { flex-grow: 4; min-height: 75px; display: flex; flex-direction: column; justify-content: center; text-align: left; font-size: 12px; line-height: 22px; letter-spacing: 9%; padding-left: 20px; } .documents-toolbar-icon { margin-right: 0px; } #download, #embed, #index, #share { -ms-grid-column: 1; -ms-grid-row: 3; } #embed-mobile-document { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-row-span: 3; grid-column-start: 1; grid-column-end: 1; grid-row-start: 1; grid-row-end: 3; z-index: 1000; background-color: white; width: 100%; height: 100%; overflow: scroll; position: relative; display: block; } .grid .column { flex: 0 0 100%; max-height: 100%; overflow: hidden; } #header { display: none; } #index { display: block; } #index-documents { display: none; } .index-content-visible { z-index: 1000; -ms-grid-column: 1; -ms-grid-row: 3; } #navigation { -ms-grid-column: 1; -ms-grid-row: 4; grid-area: index-navigation; } #navigation-mobile-display-agenda, #navigation-mobile-display-minutes, #navigation-mobile-display-documents { display: flex; } #navigation-display-download, #navigation-display-clip { display: none; } #share { justify-content: center; } #share-info-desktop { width: 100%; margin: 10px; padding: 0px 5px; } #share-link-desktop { min-width: auto; } .share-provider { margin: 0px; } #share-providers { margin: 0px; padding: 5px; } } @media all and (max-width: 1199px) { } </style> <style> </style> <style type="text/css"> html { background-color: #000000; } #header { background: url('/core/Handlers/media/attachmentdisplay.ashx?guid=5594bfa3-b190-47cc-ae6e-f807ac5b5132') no-repeat center center; background-size: contain; } } </style> <script>video_url="//cdn3.wowza.com/5/ZFdxUW9BQWt2UWRL/sanfrancisco/G0051_050/playlist.m3u8"</script> <script src="//code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script src="/js/moment.min.js"></script> <!-- slider --> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <!-- jQuery ui touch plugin for slider --> <script type="text/javascript" src="/js/jqueryui-touch-plugin.js"></script> <script src="https://cdn.flowplayer.com/releases/native/3/v3.5.0/flowplayer.min.js"></script> <script src="https://cdn.flowplayer.com/releases/native/3/v3.5.0/plugins/hls.min.js"></script> <script src="https://cdn.flowplayer.com/releases/native/3/v3.5.0/plugins/message.min.js"></script> <script src="https://cdn.flowplayer.com/releases/native/3/v3.5.0/plugins/cuepoints.min.js"></script> <script src="https://pro.fontawesome.com/releases/v5.15.3/js/all.js"></script> <script src="https://cdn.flowplayer.com/releases/native/3/v3.5.0/plugins/subtitles.min.js"></script> <link rel="stylesheet" href="https://cdn.flowplayer.com/releases/native/3/v3.5.0/style/flowplayer.css"> <style> #granicus-back, #granicus-forward, #granicus-cc { cursor: pointer; position: relative; } .flowplayer { /* overrides flowplayer css to prevent scrollbar in player */ display: block; max-width: 100%; max-height: 100%; } </style> </head> <body granicus-app="mediamanager"> <div class="grid"> <header id="header"></header> <label id="video-section-label" style="display: none;">Video Player and Subtitles</label> <section id="video" aria-labelledby="video-section-label"> <div class="responsive-error" id="player-error" style="display: none;"><span></span></div> <div id="flowplayer"></div> <div id="captions" class="flow-captions captions flex-col-center" style="display: none"> <div id="captions-line-1" class="captions-line"></div> <div id="captions-line-2" class="captions-line"></div> <div id="captions-line-3" class="captions-line"></div> </div> <div id="video-name" class="flex-col-center">SFGovTV2 LIVE (Osprey)</div> <script type="text/javascript" src="//cdn.pubnub.com/sdk/javascript/pubnub.4.13.0.js"></script> <style> #fullscreenCaptionsSpan { display: table; background-color: rgba(0,0,0,.5); font-size: 2vw; line-height: normal; margin: auto; margin-bottom: 1vw; padding: 0.5vw; } @media only screen and (max-device-width: 1023px) { #fullscreenCaptionsSpan { font-size: 4vw; } @media only screen and (orientation: landscape) { #fullscreenCaptionsSpan { font-size: 3vw; } } } </style> <script> window.captionsArray = ['','','']; window.pubnubCaptions = []; window.fullscreenCaptions = ['','','']; function ProcessPubNubSubscription() { getCurrentTime(); window.pubnub = new PubNub({ subscribeKey: "sub-c2d442a8-bc92-11e1-965d-73676a41e701", origin: 'pubsub.pubnub.com', ssl: true }); window.pnTimetoken = undefined; window.pubnub.addListener({ message: function(event) { if (event.message.type === "CONTROL") { if (window.lastStartOrStopEvent) { //added the if statement below to ensure "STOPEVENT" triggers processEvent //because there were inconsistencies in the previous logic triggering that event //there is also logic handling these events in gmp.js if (event.message.text === "STOPEVENT") { processEvent(event); } } else { window.lastStartOrStopEvent = event; setTimeout(function() { window.lastStartOrStopEvent = null; }, 60 * 1000); processEvent(event); } } else { processEvent(event); } }, status: function(status) { // pubnub and its inconsistent/weird times window.pnTimetoken = status.currentTimetoken; if (status.category === "PNNetworkDownCategory" || status.category === "PNNetworkIssuesCategory" || status.category === "PNTimeoutCategory" || status.category === "PNUnexpectedDisconnectCategory" || status.category === "PNTLSConnectionFailedCategory" || status.category === "PNUnknownCategory") { window.pubnub.reconnect() $.ajax({ type: "POST", url: "/api/metrics/frontEndLogger", data: {"message": "PubNub Disconnect: " + status.category + ""}, xhrFields: { withCredentials: true } }); 聽聽聽聽聽聽 }; } }); window.pubnubSubscriptionOffset = "" ? (parseInt("")) : (-35); if (window.videoHasBeenRecovered) { window.pubnubSubscriptionOffset = "" ? (parseInt("") -20) : (-15); } var subscriptionStartTimetoken = (window.currentPubnubTime + (window.pubnubSubscriptionOffset * 10000000)); window.pubnub.subscribe({ channels: ["sanfrancisco_encoder3"], timetoken: subscriptionStartTimetoken }); } if ((flowplayer != null) && (flowplayer.instances != null) && (flowplayer.instances[0] != null)) { flowplayer.instances[0].on('state', function(e) { if (!window.pubnub) { ProcessPubNubSubscription(); } }); } else { ProcessPubNubSubscription(); } function getCurrentTime () { window.currentPubnubTime = Date.now() * 10000; var ajax = new XMLHttpRequest(); ajax.open( 'GET', '//pubsub.pubnub.com/time/0', false ); ajax.onload = function() { if (ajax.status >= 200 && ajax.status < 400) { var data = ajax.responseText; window.currentPubnubTime = parseInt(data.substring(1, data.length - 1)); } } ajax.send(); } function formatCaption(caption) { var unicodePattern = /\/u(\d{4})/; var matches; while(matches = caption.match(unicodePattern)) { if(matches !== null && matches.length == 2) { var characterCode = parseInt(matches[1], 16); var actualCharacter = String.fromCharCode(characterCode); caption = caption.replace(matches[0], actualCharacter); } } caption = caption.replace(/(",|%26quot%3b)/g, ' ,'); return caption; } var captionsAvailable = function() { return window.pubnubCaptions && window.pubnubCaptions.length > 0; }; var flowTimeMicroseconds = function() { return flowplayer().video.time * 10000000; }; var firstCaptionTime = function() { return window.pubnubCaptions[0].timetoken; }; function pushCaption(caption) { for(var i = 1; i < 3; i++) { window.fullscreenCaptions[i-1] = window.fullscreenCaptions[i]; window.captionsArray[i-1] = window.captionsArray[i]; } window.fullscreenCaptions[2] = "<p>" + caption + "</p><br/>"; window.captionsArray[2] = caption; } var pushAndRenderCaption = function() { pushCaption(window.pubnubCaptions[0].message.text); window.pubnubCaptions.shift(); if (flowplayer().isFullscreen || embedded) { renderFullscreenCaptions(window.captionsArray); } else { renderCaptionsArray(window.captionsArray); } }; var renderCaptionsArray = function(captions) { for (var i = 1; i <= 3; i++) { $('div#captions-line-'+i).html(captions[i-1]); } } var renderFullscreenCaptions = function(captions) { var captionsString = "" for (var i = 1; i <= 3; i++) { captionsString = captionsString + "<span id='fullscreenCaptionsSpan'>" + captions[i-1] + "</span>"; } $(".fp-captions").html(captionsString); } function checkForSubString(target, searchString) { return target.indexOf(searchString) >= 0; } function includesEither(target, first, second) { var usersAgent = navigator.userAgent; if (checkForSubString(usersAgent, '.NET')) { return checkForSubString(target, first) || checkForSubString(target, second); } else { return target.includes(first) || target.includes(second); } } function recoverHlsStream(event) { window.startOrStopEventTime = event.message.time; window.pubnub.unsubscribeAll(); window.pubnubCaptions = []; window.captionOffset = undefined; window.videoHasBeenRecovered = true; flowplayer().engine.hlsjs.recoverMediaError(); hideCaptions(); } var processEvent = function(event) { switch (event.message.type) { case 'caption': event.message.text = formatCaption(event.message.text); window.pubnubCaptions.push(event); break; case 'METAJSON': var data = JSON.parse(unescape(event.message.text).replace(/"/g, '"')); if (data.type == "Granicus.MeetingDocument.AgendaItem") { document.getElementById('current-agenda-item').title = data.displayName; document.getElementById('current-agenda-item').textContent = data.displayName; } break; case 'CONTROL': var stopEvent = event.message.text === "STOPEVENT"; var startOrStopEvent = ((event.message.text === "STARTEVENT") || stopEvent); var eventPubRegEx = /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/; var windowLocation = parent.window.location.href; var publishPoint = windowLocation.indexOf("publish") > -1; if(publishPoint){ var isEvent = eventPubRegEx.test(windowLocation); } if (stopEvent && ((windowLocation.indexOf("event") > -1) || isEvent)) { if ((flowplayer != null) && (flowplayer.instances != null) && (flowplayer.instances[0] != null)) { flowplayer.instances[0].on('error', function(e) { console.log(e); }) } else { flowplayer().on("error", function(e){ console.log(e); }) } setTimeout(function(){ window.top.location.assign("/panes/endofevent.php"); }, 35000); } else if (startOrStopEvent && includesEither(windowLocation, "publish", "camera")) { setTimeout(function() { recoverHlsStream(event); }, 3000); } break; default: console.log('Uncaught event type:'); console.log(event.message); } } var embedded = isEmbedded(); window.captionOffset = undefined; </script> </section> <label id="index-section-label" style="display: none;">Video Indices</label> <section id="index" aria-labelledby="index-section-label" class="index-content index-content-visible"> <div class="current-item flex-col-center"> <span class="current-item-label">Current Item</span> <span id="current-agenda-item" class="current-item-value overflow-ellipsis" title="" > </span> </div> </section> <section id="embed" class="index-content"> <div id="embed-content"> <div id="embed-info-desktop"> <div id="embed-size"> <div id="embed-width"> <label id="embed-width-label">Player Width (px):</label> <input id="embed-width-input" type="text" title="Set Custom Player Width" aria-labelledby="embed-width-label" value="640" onChange="updateEmbedCodeOnChange();" size="4"/> </div> <div id="embed-height"> <label id="embed-height-label">Player Height (px):</label> <input id="embed-height-input" type="text" title="Set Custom Player Height" aria-labelledby="embed-height-label" value="360" onChange="updateEmbedCodeOnChange();" size="4"/> </div> </div> <div id="embed-autoplay"> <input id="embed-autostart-checkbox" type="checkbox" title="Embed Autoplay" aria-labelledby="embed-autostart-checkbox" onChange="updateEmbedCodeOnChange();"> Start playing automatically when loaded </input> </div> <div id="embed-slider-display"> </div> <div id="embed-slider"> <div id="durationSlider" width="400px" class="durationSlider"></div> </div> <div id="embed-link-desktop"> <label id="embed-link-desktop-label"> Copy this html to embed into your page </label> <br> <input id="embed-link-desktop-input" type="text" title="Link to Video" aria-labelledby="embed-link-desktop-label" readonly></input> </div> </div> </div> </section> <!-- <script src="/js/moment.min.js"></script> --> <!-- slider --> <!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> --> <!-- jQuery ui touch plugin for slider --> <!-- <script type="text/javascript" src="/js/jqueryui-touch-plugin.js"></script> --> <section id="share" class="index-content"> <div id="share-content"> <div id="share-info-desktop"> <label id="share-item-label">Share the current item or the full video:</label> <div class="share-info-item"> <input type="radio" title="Start from Current Item" aria-labelledby="share-item-label" onClick="setShareLinkAndCheckRadio(true, this)">Start From Current Item</input> </div> <div class="share-info-item"> <input type="radio" title="Full Video" aria-labelledby="share-item-label" checked="checked" onClick="setShareLinkAndCheckRadio(false, this)">Full Video</input> </div> <div id="share-link-desktop"> <label id="share-link-desktop-label"> Copy this link to send this event to your friends: </label> <br> <input type="text" title="Link to Video" aria-labelledby="share-link-desktop-label" readonly></input> </div> </div> <div id="share-providers"> <a target="_blank" class="share-provider flex-col-center" href="mailto:example@email.com?body=https://sanfrancisco.granicus.com/player/camera/50"> <span class="fa-layers fa-fw"> <i class="fas fa-circle" id="email" data-fa-transform="grow-30"></i> <i class="far fa-envelope fa-inverse" data-fa-transform="grow-16"></i> </span> <div class="share-provider-name"> Email </div> </a> <a target="_blank" class="share-provider flex-col-center" href="https://www.facebook.com/sharer/sharer.php?u=https://sanfrancisco.granicus.com/player/camera/50&amp;t=SFGovTV2 LIVE (Osprey)"> <span class="fa-layers fa-fw"> <i class="fas fa-circle" id="facebook" data-fa-transform="grow-30"></i> <i class="fab fa-facebook-f fa-inverse" data-fa-transform="grow-16"></i> </span> <div class="share-provider-name"> Facebook </div> </a> <a target="_blank" class="share-provider flex-col-center" href="https://www.linkedin.com/shareArticle?mini=true&amp;url=https://sanfrancisco.granicus.com/player/camera/50&amp;title=SFGovTV2 LIVE (Osprey)&amp;source=https://sanfrancisco.granicus.com"> <span class="fa-layers fa-fw"> <i class="fas fa-circle" id="linked-in" data-fa-transform="grow-30"></i> <i class="fab fa-linkedin-in fa-inverse" data-fa-transform="grow-16 right-2"></i> </span> <div class="share-provider-name"> LinkedIn </div> </a> <a target="_blank" class="share-provider flex-col-center" href="https://www.twitter.com/intent/tweet?url=https://sanfrancisco.granicus.com/player/camera/50&amp;text=SFGovTV2 LIVE (Osprey)"> <span class="fa-layers fa-fw"> <i class="fas fa-circle" id="twitter" data-fa-transform="grow-30"></i> <i class="fab fa-twitter fa-inverse" data-fa-transform="grow-16"></i> </span> <div class="share-provider-name"> Twitter </div> </a> </div> </div> </section> <section id="index-documents" role="tabpanel"> <div id="index-documents-toolbar" role="tablist"> <div class="documents-toolbar-item" id="desktop-default-document" role="tab" tabindex="0" aria-selected="false" data-url="https://sfgovtv.org/ch2calendar"> <div class="documents-toolbar-icon fa fa-file fa-lg"></div> <div class="documents-toolbar-text">Default Document</div> </div> <div class="documents-toolbar-item streaming-help" role="tab" tabindex="0" aria-selected="false" data-url="//support.granicus.com/s/article/Public-Help-Video-Streaming"> <div class="documents-toolbar-icon fa fa-question-circle fa-lg"></div> <div class="documents-toolbar-text">Streaming Video Support</div> </div> </div> <div class="documents-default-document" data-url="https://sfgovtv.org/ch2calendar" data-selected="desktop-default-document"></div> </section> <div id="content-documents" class="index-content"> <div class="grid"> <label id="documents-section-label" style="display: none;">Documents</label> <section id="documents" aria-labelledby="documents-section-label" class="center-center"> <a class="document-group"> <div class="document-label flex-col-center">Default Document</div> <div class="document" data-url="https://sfgovtv.org/ch2calendar"> <div class="document-icon-green flex-col-center"> <div class="documents-toolbar-icon fa fa-file fa-lg"></div> </div> <div class="document-text">Default Document</div> </div> </a> </section> </div> </div> <label id="navigation-label-desktop" style="display: none;">Navigation</label> <nav id="navigation" aria-labelledby="navigation-label-desktop" class="center-center column navigation-desktop"> <a id="navigation-display-index" class="navigation-element selected" href="javascript:swapIndexContent('index');" title="Index"> <span class="fa fa-list navigation-icon fa-lg"></span> <div class="navigation-text">Index</div> </a> <a id="navigation-mobile-display-documents" class="navigation-element" href="javascript:swapIndexContent('content-documents');" title="Documents"> <span class="fa fa-paperclip navigation-icon fa-lg"></span> <div class="navigation-text">Documents</div> </a> <a class="navigation-element" href="javascript:swapIndexContent('share');" title="Share"> <span class="fa fa-share-square navigation-icon fa-lg"></span> <div class="navigation-text">Share</div> </a> <a id="navigation-display-clip" class="navigation-element" title="Embed" href="javascript:swapIndexContent('embed');"> <span class="fa fa-exchange navigation-icon fa-lg"></span> <div class="navigation-text">Embed</div> </a> </nav> </div> <script async src="https://www.googletagmanager.com/gtag/js?id=G-B9CKXY5LYZ"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'G-B9CKXY5LYZ', { 'request_origin':'external' }); </script> <script type="text/javascript"> // Set up video and player template values var isLive = true; var shouldAutoplay = false; var captionsEnabled = true; var granicusCaptions = false; // Configure flowplayer-7-only variables and functions // Configuring flowplayer native options var options = { token: "eyJraWQiOiJuVWUxWmVVeWZ5b0kiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjIjoie1wiYWNsXCI6NixcImlkXCI6XCJuVWUxWmVVeWZ5b0lcIn0iLCJpc3MiOiJGbG93cGxheWVyIn0.JuVr0Jt6S-C6TK-vYBgPBTfdxo8RKdcNFm46iZsVSX5PfWSZhwZea3EW4M-OnGjsj0HzZ_uD5giNGXCQe2veJw", src: "//cdn3.wowza.com/5/ZFdxUW9BQWt2UWRL/sanfrancisco/G0051_050/playlist.m3u8", autoplay: shouldAutoplay, volume: 1, live: isLive, subtitles: {tracks: []} } // Construct the player var native_video = flowplayer("#flowplayer", options) native_video.on(flowplayer.events.CUEPOINT_START, function(e) { markCurrentIndexItem(e.data.cuepoint); }) // Find the reference elements we need const controls = native_video.root.querySelector(".fp-controls") const live_status = native_video.root.querySelector(".fp-live-status") const targetDivLiveCaptions = document.getElementById("captions"); // Create custom buttons const granicus_caption_button = document.createElement("span"); const backward_button = document.createElement("span") const forward_button = document.createElement("span") // Style custom buttons granicus_caption_button.innerHTML = '<span id="granicus-cc">CC</span>' backward_button.innerHTML = '<span id="granicus-back" class="fa-layers fa-fw"><i class="fas fa-undo-alt" data-fa-transform="rotate--315 grow-17"></i><span class="fa-layers-text fa-inverse" data-fa-transform="shrink-5 down-10 right-9" style="font-weight:900">15</span></span>' forward_button.innerHTML = '<span id="granicus-forward" class="fa-layers fa-fw"><span class="fa-layers-text fa-inverse" data-fa-transform="shrink-5 down-10 right-9" style="font-weight:900">15</span><i class="fas fa-redo-alt" data-fa-transform="rotate--45 grow-18"></i></span>' // Add granicus captions if live and captions enabled and granicus captions enabled if (captionsEnabled && granicusCaptions && isLive) { addGranicusCaptions(granicus_caption_button, controls) } // Add custom seek buttons if not live if (!isLive) { live_status.before(forward_button) forward_button.before(backward_button) } // Adds the custom granicus captions button function addGranicusCaptions(button, controls) { controls.appendChild(button) } // Custom button onclick functions granicus_caption_button.onclick = function() { if (targetDivLiveCaptions.style.display === "block") { targetDivLiveCaptions.style.display = "none"; } else { targetDivLiveCaptions.style.display = "block"; } } backward_button.onclick = function() { native_video.currentTime = native_video.currentTime - 15; } forward_button.onclick = function() { native_video.currentTime = native_video.currentTime + 15; } function SetPlayerPosition(time) { native_video.currentTime = time.replace(":", ''); } var clearErrorMessages = function() { $('.fp-message').hide(); $('.responsive-error span').text(''); $('.flowplayer').show(); $('.responsive-error').hide(); } var showErrorMessage = function(errorMessage) { $('.responsive-error span').text(errorMessage); $('.flowplayer').hide(); $('.responsive-error').show(); } var setEmbedCode = function(code) { $('#embed-code').val(code); } var setCurrentItem = function(item) { $('#current-index-title').html(item); } document.addEventListener("DOMContentLoaded", function() { flowplayer(function(api, root) { api.on('ready', function(){ clearErrorMessages(); }); api.on('error', function (e, api, err) { var errorMessage = null; if (/rv:11.0/i.test(navigator.userAgent)) { // Use built in Flowplayer errors for IE. } else { if (err.code == 4) { errorMessage = "This video file was not found, please try again later."; } else if (err.code == 2) { errorMessage = "Network error occurred, please refresh the page and try again."; } else { errorMessage = $('.fp-message').text(); } showErrorMessage(errorMessage); } }); }); }) </script> <script type="text/javascript"> const recordedItems = document.querySelectorAll('.index-point[role="tab"]'); recordedItems.forEach(recordedItem => { recordedItem.addEventListener('keydown', indexItemClickHandler); }); function indexItemClickHandler(event) { const key = event.key; const targetPoint = event.currentTarget; switch (key) { case 'Enter': targetPoint.click(); break; default: return; } } $('.index-point').on("click", function() { var that = $(this); flowplayer().seek(that.attr("time")); cycleMenuHighlighting('.index-point.', 'selected', that); }); </script> <script> var lastSliderStart = 0; var lastSliderStop = null; $(document).ready(function(){ // Display Embed Code on page load | KS | CSI-321 updateEmbedCodeOnChange(); }); function setEmbedCode(width, height, startTime, stopTime, autoStart) { var autoStartCode = '&autostart=' + (autoStart ? 1 : 0); var startCode = '', embedCode = ''; width = width + 'px'; height = height + 'px'; embedCode = '<embed width="' + width + '" height="' + height + '" ' + 'frameborder="0" allowfullscreen="true" src="' + window.location.href.substring(window.location.protocol.length) + autoStartCode +'&embed=1"></embed>'; $('#embed-link-desktop-input').val(embedCode); } function updateEmbedCodeOnChange() { var start = "", stop = ""; var width = $('#embed-width-input')[0].value; var height = $('#embed-height-input')[0].value; var autostart = $('#embed-autostart-checkbox')[0].checked setEmbedCode(width, height, start, stop, autostart); } $('#embed-slider-display').hide(); $('#embed-slider').hide(); </script> <script type="text/javascript"> function swapIndexContent(targetID) { var visibleIndexContentClass = 'index-content-visible'; $('.' + visibleIndexContentClass).removeClass(visibleIndexContentClass); $('#' + targetID).addClass(visibleIndexContentClass); } function slidePane(targetPane) { var visibleSlidePaneClass = 'sliding-pane-visible'; document.getElementsByClassName(visibleSlidePaneClass)[0].classList.remove(visibleSlidePaneClass); document.getElementById(targetPane).classList.add(visibleSlidePaneClass); } $('#navigation > .navigation-element').on("click", function() { $('#embed-mobile-document').remove(); $('#ios-mobile-document').remove(); cycleMenuHighlighting('.navigation-element.', 'selected', $(this)); }); </script> <script type="text/javascript"> function createDesktopDocument(slideLink) { var documentToolbarItem = createDiv({ class: 'documents-toolbar-item', "data-url": slideLink }), documentToolbarItemIcon = createDiv({ class: 'documents-toolbar-icon fa fa-file fa-lg' }), documentToolbarItemText = createDiv({ class: 'documents-toolbar-text', text: 'Slide'}); $('#index-documents-toolbar').append(documentToolbarItem); documentToolbarItem.append(documentToolbarItemIcon); documentToolbarItem.append(documentToolbarItemText); documentToolbarItem.on("click", setDocumentsToolbarItemListener); documentToolbarItem.trigger('click'); } function createDiv(divProperties) { return $('<div/>', divProperties); } function createMobileDocument(slideLink) { var documentGroup = $('<a/>', { class: 'document-group' }), documentIconBackground = createDiv({ class: 'document-icon-gray flex-col-center' }), documentIcon = createDiv({ class: 'documents-toolbar-icon fa fa-file fa-lg' }), documentLabel = createDiv({ class: 'document-label flex-col-center', text: 'Slide' }), documentLink = createDiv({ class: 'document', 'data-url': slideLink }), documentText = createDiv({ class: 'document-text', text: 'Slide' }), mobileDocumentList = $('#documents'); mobileDocumentList.prepend(documentGroup); documentGroup.append(documentLabel); documentGroup.append(documentLink); documentLink.append(documentIconBackground); documentIconBackground.append(documentIcon); documentLink.append(documentText); documentLink.on("click", setDocumentsToolbarItemListener); var noDocumentsMessage = $('#no-documents-available'); if (noDocumentsMessage.length) { noDocumentsMessage.remove(); } } function cycleDocumentView(url, mobile, target) { var isIphone = navigator.userAgent.indexOf("iPhone") != -1 ; var isIpod = navigator.userAgent.indexOf("iPod") != -1 ; var isIpad = navigator.userAgent.indexOf("iPad") != -1 ; // now set one variable for all iOS devices var isIos = isIphone || isIpod || isIpad ; if (mobile) { if (isIos) { loadIOSEmbed(url, target, true); } else { loadEmbed(url, target, true); } } else { target.empty(); loadEmbed(url, target, false); } } function cycleMenuHighlighting(elementClass, selectedElementClass, selectedElement) { $(elementClass + selectedElementClass).removeClass(selectedElementClass); selectedElement.addClass(selectedElementClass); } function loadEmbed(url, target, insertBefore) { var identifier = insertBefore ? target : 'documents-viewer-iframe', embedElement = $('<embed>', { src: url, id: identifier, type: 'text/html' }); insertBefore ? embedElement.insertBefore('#navigation') : embedElement.appendTo(target); } function loadIOSEmbed(url,target,insertBefore){ window.open(url, "_blank"); } function markCurrentIndexItem(cuepoint) { if (cuepoint.type == "Document") { var slideLink = location.protocol + "//" + location.host + '/MetaViewer.php?meta_id=' + cuepoint.id; if ($('.documents-default-document').is(":visible")) { var existingSlide = $('.documents-toolbar-item > .documents-toolbar-text:contains("Slide")'); if (existingSlide.length) { existingSlide.parent().remove(); } createDesktopDocument(slideLink); } else { var existingSlide = $('.document > .document-text:contains("Slide")'); if (existingSlide.length) { existingSlide.parent().parent().remove() } createMobileDocument(slideLink); } } var indexPoints = $('.index-point'); indexPoints.each(function(index, element) { if (cuepoint.time >= element.attributes.time.value && (index == indexPoints.length - 1 || cuepoint.time < indexPoints[index + 1].attributes.time.value)) { cycleMenuHighlighting('.index-point.', 'selected', $(element)); } }); } function setDocumentsToolbarItemListener() { var that = $(this), documentURL = that.data('url'), mobileDocumentDisplay = 'embed-mobile-document', desktopDisplay = $('.documents-default-document'); if (that.hasClass('streaming-help')){ window.open(that.data('url')); } else if (desktopDisplay.is(":visible")) { cycleMenuHighlighting('.documents-toolbar-item.', 'selected-document', that); cycleDocumentView(documentURL, false, desktopDisplay); } else { cycleDocumentView(documentURL, true, mobileDocumentDisplay); } } function setShareLinkAndCheckRadio(currentItem, that) { $('.share-info-item > input:checked').prop('checked', false); var currentSelectedItemID = $('.index-point.selected').data('id'); var currentLocation = location.protocol + '//' + location.host + location.pathname; if (currentItem && currentSelectedItemID) { var shareLink = currentLocation + '?meta_id=' + currentSelectedItemID; } else { var shareLink = currentLocation; } $('#share-link-desktop > input').val(shareLink); $(that).prop('checked', true); } function hackIE () { var maxMobile = 1023; // Max Mobile Width in Pixels var minIndexHeight = 300; var captionsHeight = 100; // reset any prior heights set by hackIE() $('#index').css('height', ''); $('#index').css('display', ''); $('#video').css('height', ''); if ($(window).width() > maxMobile) { var windowHeight = $(window).height(); var headerHeight = $('header').height(); var videoHeight = $('#video').height(); var navigationHeight = $('#navigation').height(); var indexHeight = windowHeight - headerHeight - videoHeight - navigationHeight; if (indexHeight < minIndexHeight) { indexHeight = minIndexHeight; videoHeight = windowHeight - headerHeight - navigationHeight - indexHeight; $('#video').height(videoHeight); } // If captions are on, force flowplayer video height to allow for captions frame. if ($('#captions').css('display') == 'block') { var flowplayerHeight = videoHeight - captionsHeight; $('.flowplayer').height(flowplayerHeight); } $('#index').height(indexHeight); $('#index').css('display', 'block'); $('#index').css('min-height', '100px'); } else { $('#index').css('height', ''); $('#index').css('display', ''); $('video').css('height', ''); } } window.onresize = function (event) { if (navigator.userAgent.match(/Trident\/7\./)) { hackIE(); } } $(document).ready(function() { var docURL = $('.documents-default-document').data('url'); var docType = $('.documents-default-document').data('selected'); if (docType != "noDoc") { $('#'+docType).addClass('selected-document'); } loadEmbed(docURL, '.documents-default-document', false); if ($('documents-default-document')) $('.document, .documents-toolbar-item, #navigation-mobile-display-agenda, #navigation-mobile-display-minutes').on("click", setDocumentsToolbarItemListener); var currentLocation = location.protocol + '//' + location.host + location.pathname; $('#share-link-desktop > input').val(currentLocation); if (flowplayer != null && (flowplayer.instances == null)) { flowplayer().on('cuepoint', function(e, api, cuepoint) { markCurrentIndexItem(cuepoint); }); flowplayer().on('seek', function(e, api, time) { markCurrentIndexItem({ time: time, type: "Seek" }); }); flowplayer().on('fullscreen', function(e, data){ var desktopDocument = $('.documents-default-document'); if (desktopDocument.is(':visible')) { desktopDocument.hide(); } }); flowplayer().on('fullscreen-exit', function(e, api) { var desktopDocumentToolbar = $('#index-documents-toolbar'); if (desktopDocumentToolbar.is(':visible')) { $('.documents-default-document').show(); } }); } if (navigator.userAgent.match(/Trident\/7\./)) { hackIE(); } const tabs = document.querySelectorAll('.documents-toolbar-item[role="tab"]'); tabs.forEach(tab => { tab.addEventListener('focus', (event) => { tab.click(); // Trigger the click event immediately when the tab receives focus }); }); }); </script> </body> </html>