function get_stream_cmml( $inline = false, $force_track = null ) { $dbr = wfGetDB( DB_SLAVE ); // set cmml name space if inline: $ns = ( $inline ) ? 'cmml:':''; $ns = ''; $encap = false;// if we should have a parent cmml tag if ( !$force_track ) { // check the request to get trac set: $mvcp = new MV_Component(); $mvcp->procMVDReqSet(); $tracks = $mvcp->mvd_tracks; if ( count( $mvcp->mvd_tracks ) > 1 )$encap = true; } else { $tracks = $force_track; $encap = false; } // get the stream title $streamTitle = new MV_Title( $this->stream_name . '/' . $this->req_time ); $wgTitle = Title::newFromText( $this->stream_name . '/' . $this->req_time, MV_NS_STREAM ); // do mvd_index query: $mvd_rows = MV_Index::getMVDInRange( $streamTitle->getStreamId(), $streamTitle->getStartTimeSeconds(), $streamTitle->getEndTimeSeconds(), $tracks, $getText = false, 'Speech_by,Bill,category' ); // get the stream stream req if ( $this->output_xml_header ) header( 'Content-Type: text/xml' ); // print the header: if ( !$inline )print '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' . "\n"; // if(!$inline)print '<!DOCTYPE cmml SYSTEM "http://svn.annodex.net/standards/cmml_2_0.dtd">'."\n"; $tracks = array(); if ( count( $mvd_rows ) != 0 ) { global $wgOut; $MV_Overlay = new MV_Overlay(); foreach ( $mvd_rows as $mvd ) { if ( !isset( $tracks[$mvd->mvd_type] ) )$tracks[$mvd->mvd_type] = ''; $tracks[$mvd->mvd_type] .= ' <' . $ns . 'clip id="mvd_' . htmlentities( $mvd->id ) . '" start="npt:' . htmlentities( seconds2npt( $mvd->start_time ) ) . '" end="npt:' . htmlentities( seconds2npt( $mvd->end_time ) ) . '"> <' . $ns . 'img src="' . htmlentities( $streamTitle->getFullStreamImageURL( null, seconds2npt( $mvd->start_time ) ) ) . '"/>'; // output all metadata @@todo we should generalize the semantic properties. $tracks[$mvd->mvd_type] .= ( isset( $mvd->Speech_by ) && trim( $mvd->Speech_by ) != '' ) ? '<meta name="Speech_by" content="' . htmlentities ( $mvd->Speech_by ) . '"/>':''; $tracks[$mvd->mvd_type] .= ( isset( $mvd->Bill ) && trim( $mvd->Bill ) != '' ) ? '<meta name="Bill" content="' . htmlentities( $mvd->Bill ) . '"/>':''; // add in categories as "keywords" if ( count( $mvd->category ) != 0 ) { $tracks[$mvd->mvd_type] .= '<meta name="keywords" content="'; $coma = ''; foreach ( $mvd->category as $cat ) { $tracks[$mvd->mvd_type] .= $coma . htmlentities( $cat ); $coma = ','; } $tracks[$mvd->mvd_type] .= '"/>'; } $tracks[$mvd->mvd_type] .= '<' . $ns . 'body><![CDATA[ ' . $MV_Overlay->getMVDhtml( $mvd, $absolute_links = true ). ' ]]></' . $ns . 'body> </' . $ns . 'clip>'; // clear wgOutput } } if ( $encap )print '<cmml_set>'; // based on: http://trac.annodex.net/wiki/CmmlChanges foreach ( $tracks as $role => $body_string ) { $ns = htmlentities( $ns ); ?> <cmml lang="en" id="<?php echo htmlentities($role); ?> " role="<?php echo wfMsg($role); ?> " xmlns="http://svn.annodex.net/standards/cmml_2_0.dtd"> <<?php echo $ns; ?> head> <<?php echo $ns; ?> title> <?php echo wfMsg($role); ?> </<?php echo $ns; ?> title> <<?php echo $ns; ?> meta name="description" content="<?php echo htmlentities(wfMsg($role . '_desc')); ?> "></<?php echo $ns; ?> meta> </<?php echo $ns; ?> head> <?php echo $body_string; ?> </cmml> <? } if ( $encap )print '</cmml_set>'; }
/** * outputs basic stream paging (this could be done client side) * */ function stream_paging_links($return_set = 'both') { global $wgUser, $mvDefaultStreamViewLength, $mvgScriptPath; $sk = $wgUser->getSkin(); $prev_link = $next_link = ''; // check if their is prev available: $mvTitle = $this->mv_interface->article->mvTitle; if ($return_set == 'both' || $return_set == 'prev') { if ($mvTitle->getStartTimeSeconds() > 0) { $prev_time_start = $mvTitle->getStartTimeSeconds() - $mvDefaultStreamViewLength; if ($prev_time_start < 0) { $prev_time_start = 0; } $prev_time_end = $mvTitle->getEndTimeSeconds() - $mvDefaultStreamViewLength; if ($prev_time_end < $mvDefaultStreamViewLength) { $prev_time_end = $mvDefaultStreamViewLength; } $newTitle = Title::MakeTitle(MV_NS_STREAM, $mvTitle->getStreamName() . '/' . seconds2npt($prev_time_start) . '/' . seconds2npt($prev_time_end)); $prev_link = $sk->makeKnownLinkObj($newTitle, '<img style="index:5" border="0" src="' . htmlspecialchars($mvgScriptPath) . '/skins/images/results_previous.png">', $this->getStateReq()); } } if ($return_set == 'both' || $return_set == 'next') { if ($mvTitle->getDuration() != $mvTitle->getEndTimeSeconds()) { $next_time_start = $mvTitle->getEndTimeSeconds(); $next_time_end = $mvTitle->getEndTimeSeconds() + $mvDefaultStreamViewLength; if ($next_time_end > $mvTitle->getDuration()) { $next_time_end = $mvTitle->getDuration(); } $newTitle = Title::MakeTitle(MV_NS_STREAM, $mvTitle->getStreamName() . '/' . seconds2npt($next_time_start) . '/' . seconds2npt($next_time_end)); $next_link = $sk->makeKnownLinkObj($newTitle, '<img style="index:5" border="0" src="' . htmlspecialchars($mvgScriptPath) . '/skins/images/results_next.png">', $this->getStateReq()); } } if ($return_set == 'both') { return $prev_link . ' ' . $next_link; } if ($return_set == 'prev') { return $prev_link; } if ($return_set == 'next') { return $next_link; } }
function getItemOutput($row, $opt = array()) { global $wgUser; $sk = $wgUser->getSkin(); //set defaults: $person_ht = $bill_ht = $category_ht = $o = ''; if (!isset($row->start_time)) { $row->start_time = 0; } if (!isset($row->end_time)) { $row->end_time = 60 * 20; } $mvd_out_html = ''; $mvd_rows = MV_Index::getMVDInRange($row->stream_id, $row->start_time, $row->end_time, $mvd_type = 'anno_en', $getText = true, $smw_properties = array('Speech_by', 'Bill', 'category'), $options = array('limit' => 1)); if (count($mvd_rows) != 0) { reset($mvd_rows); $mvd_row = current($mvd_rows); if (isset($opt['use_mvd_time']) && $opt['use_mvd_time']) { $row->start_time = $mvd_row->start_time; $row->end_time = $mvd_row->end_time; } // print_r($mvd_rows); // print "type of: " . gettype($mvd_row); if (isset($mvd_row->Speech_by)) { if (trim($mvd_row->Speech_by) != '') { $ptitle = Title::MakeTitle(NS_MAIN, $mvd_row->Speech_by); $mvd_out_html .= '<span class="keywords">' . $sk->makeKnownLinkObj($ptitle, $ptitle->getText()) . '</span><br />'; } } if (isset($mvd_row->Bill)) { if (trim($mvd_row->Bill) != '') { $btitle = Title::MakeTitle(NS_MAIN, $mvd_row->Bill); $mvd_out_html .= '<span class="keywords">Bill: ' . $sk->makeKnownLinkObj($btitle) . ' </span><br />'; } } global $wgContLang; $mvdNStxt = $wgContLang->getNsText(MV_NS_MVD); //grab categories if no bill or speech if ($this->params['display_cat'] || $mvd_out_html == '') { $dbr = wfGetDB(DB_READ); $cl_res = $dbr->select('categorylinks', 'cl_to', array('cl_sortkey' => $mvdNStxt . ':' . str_replace('_', ' ', $mvd_row->wiki_title)), 'getTopClips::Categories', 'LIMIT 0, 5'); if ($dbr->numRows($cl_res) != 0) { $mvd_out_html .= '<span class="keywords">Categories: '; $coma = ''; while ($cl_row = $dbr->fetchObject($cl_res)) { $cTitle = Title::MakeTitle(NS_CATEGORY, $cl_row->cl_to); $mvd_out_html .= $coma . $sk->makeKnownLinkObj($cTitle, $cTitle->getText()); $coma = ', '; } $mvd_out_html .= '</span><br />'; } } } else { //we have not meta //if( isset($opt['remove_no_meta']) && $opt['remove_no_meta']) //return false; } // first make link and stream title: $mvStream = MV_Stream::newStreamByID($row->stream_id); if (!$mvStream->doesStreamExist()) { return false; } //limit our output range to < 20 min if ($row->end_time - $row->start_time > 20 * 60) { $row->end_time = $row->start_time + 20 * 60; } $nt = $mvStream->getStreamName() . '/' . seconds2npt($row->start_time) . '/' . seconds2npt($row->end_time); $mvTitle = new MV_Title($nt, MV_NS_STREAM); $mvStreamTitle = Title::MakeTitle(MV_NS_STREAM, $mvTitle->getNearStreamName($extra_range = '0')); // output the image: $o .= $sk->makeKnownLinkObj($mvStreamTitle, '<img alt="image for ' . $mvTitle->getStreamNameText() . ' ' . $mvTitle->getTimeDesc() . '" src="' . $mvTitle->getStreamImageURL('small') . '"/>', 'tl=1'); $title_span = ''; if (isset($mvStream->date_start_time)) { $parts = split('_', $mvStream->getStreamName()); if (count($parts) >= 3) { $title_span = ucfirst($parts[0] . ' '); } else { $title_span = $mvStream->getStreamName(); } $title_span .= date('F jS, Y', $mvStream->date_start_time); } else { $title_span = $mvTitle->getStreamNameText() . $mvTitle->getTimeDesc(); } $o .= '<span class="title">' . $sk->makeKnownLinkObj($mvStreamTitle, $title_span, 'tl=1') . '</span>'; //add mvd_annotative output: $o .= $mvd_out_html; return $o; }
function get_adjust_disp($titleKey = 'new', $mvd_id = 'new') { global $mvgScriptPath; // $out = ''; if ($mvd_id == 'new' || $mvd_id == 'seq') { global $mvDefaultClipLength; $start_time = isset($this->start_context) ? $this->start_context : seconds2npt(0); $end_time = isset($this->end_context) ? seconds2npt(npt2seconds($this->start_context) + $mvDefaultClipLength) : seconds2npt($mvDefaultClipLength); } else { $mvTitle = new MV_Title($titleKey); if (!$mvTitle->validRequestTitle()) { return wfMsg('mvMVDFormat'); } $start_time = $mvTitle->getStartTime(); $end_time = $mvTitle->getEndTime(); } if ($start_time == "null") { $start_time = '0:00:00'; } /* * @@todo move some of this to CSS */ $mvd_id = htmlspecialchars($mvd_id); $mvgScriptPath = htmlspecialchars($mvgScriptPath); $out .= '<br /><div class="inOutSlider"></div><br />'; $out .= '<span style="float:left;"><label class="mv_css_form" for="mv_start_hr_' . $mvd_id . '"><i>' . wfMsg('mv_start_desc') . ':</i></label> ' . '<input class="mv_adj_hr" size="8" maxlength="8" value="' . htmlspecialchars($start_time) . '" id="mv_start_hr_' . $mvd_id . '" name="mv_start_hr_' . $mvd_id . '">' . '</span>'; $out .= '<span style="float:left;"><label class="mv_css_form" for="mv_end_hr_' . $mvd_id . '"><i>' . wfMsg('mv_end_desc') . ':</i></label> ' . '<input class="mv_adj_hr" size="8" maxlength="8" value="' . htmlspecialchars($end_time) . '" id="mv_end_hr_' . $mvd_id . '" name="mv_end_hr_' . $mvd_id . '">' . '</span>'; // output page text (if not "new") // if($mvd_id!='new') // $out.=$this->get_fd_mvd_request( $titleKey, $mvd_id); /*$out.='<table width="100%">'. '<tr><td>'.wfMsg('mv_start_desc').'</td>'. '<td><input name="mv_start_hr_'.$mvd_id.'" type="text" value=""></td>'. '</tr><tr>'. '<input type="text" value=""><br /> */ // clear any floats: $out .= '<div style="clear:both"></div>'; // $out.='</form>'; return $out; }
for ($i = 0; $i < $duration; $i += $interval) { //only run the ffmpeg cmd if we have to: if (!is_file("{$filedir}/{$i}.jpg") || $overwrite_image) { if (is_file("{$filedir}/{$i}.jpg")) { print "overwriting image: {$i}.jpg\n"; shell_exec("rm {$filedir}/{$i}.jpg"); } shell_exec("ffmpeg -ss {$i} -i {$filename} -vcodec mjpeg -vframes 1 -an -f rawvideo -y {$filedir}/{$i}.jpg 2>&1"); } if (is_file("{$filedir}/{$i}.jpg")) { //insert the image into the db: $dbw->query("INSERT INTO `mv_stream_images` (`stream_id`, `time`) VALUES ({$stream_id}, {$i})"); //get ocr: shell_exec("convert {$filedir}/{$i}.jpg -crop 457x30+63+358 {$workingdir}/temp.{$stream_id}.ocr.tif && convert {$workingdir}/temp.{$stream_id}.ocr.tif -resize 300% -level 10%,1,20% -monochrome +compress {$workingdir}/temp.{$stream_id}.ocr.tif"); shell_exec("tesseract {$workingdir}/temp.{$stream_id}.ocr.tif {$workingdir}/ocrtemp{$stream_id} nobatch lettersonly 2>&1"); $ocr = shell_exec("tail {$workingdir}/ocrtemp{$stream_id}.txt") . " at " . seconds2npt($i) . " \n"; echo 'got ocr:' . $ocr; $ocroutput .= $ocr; } else { print "failed to create file: {$filedir}/{$i}.jpg \n"; } } //remove temporary files: shell_exec("rm {$workingdir}/ocrtemp{$i}.txt"); shell_exec("rm {$workingdir}/temp.{$stream_id}.ocr.tif"); $ocrfileloc = "{$workingdir}/{$stream_name}.ocr"; $fh = fopen($ocrfileloc, 'w') or die("can't write ocr file"); fwrite($fh, $ocroutput); fclose($fh); function getDuration($filename) {
/** * for each image add it to the image directory */ function do_process_images($stream, $force = false) { global $mvLocalImgLoc, $MVStreams, $wgDBname; $dbr = wfGetDB(DB_SLAVE); $dbw = wfGetDB(DB_MASTER); // get all images for the current stream: $sql = "SELECT * FROM `metavid`.`image_archive`\n\t\t\t\tWHERE `stream_fk`= {$stream->id}"; $image_res = $dbr->query($sql); $img_count = $dbr->numRows($image_res); print "Found " . $img_count . " images for stream " . $stream->name . "\n"; // grab from metavid and copy to local directory structure: $i = $j = 0; $mv_stream_id = $MVStreams[$stream->name]->getStreamId(); // if force we can clear out existing images: if ($force) { print "force update flag (remove all existing images)\n"; $local_img_dir = MV_StreamImage::getLocalImageDir($mv_stream_id); $res = $dbr->query("SELECT * FROM `{$wgDBname}`.`mv_stream_images` WHERE `stream_id`={$mv_stream_id}"); while ($row = $dbr->fetchObject($res)) { $local_img_file = $local_img_dir . '/' . $row->time . '*.jpg'; shell_exec('rm -f ' . $local_img_file); } // remove db entries: $dbw->query("DELETE FROM `{$wgDBname}`.`mv_stream_images` WHERE `stream_id`={$mv_stream_id}"); } while ($row = $dbr->fetchObject($image_res)) { // if(isset($row-> $relative_time = $row->time - $stream->adj_start_time; // status updates: if ($i == 10) { print "On image {$j} of {$img_count} time: " . seconds2npt($relative_time) . " {$metavid_img_url}\n"; $i = 0; } $j++; $i++; // get streamImage obj: $local_img_dir = MV_StreamImage::getLocalImageDir($mv_stream_id); $metavid_img_url = 'http://metavid.org/image_media/' . $row->id . '.jpg'; $local_img_file = $local_img_dir . '/' . $relative_time . '.jpg'; // check if the image already exist in the new table $sql = "SELECT * FROM `{$wgDBname}`.`mv_stream_images` " . "WHERE `stream_id`={$mv_stream_id} " . "AND `time`={$relative_time}"; $img_check = $dbr->query($sql); $doInsert = true; if ($dbr->numRows($img_check) != 0) { // make sure its there and matches what it should be: if (is_file($local_img_file)) { $row = $dbr->fetchObject($img_check); // print "file $local_img_file skiped, stream_id:" . $mv_stream_id . " time: " . seconds2npt($relative_time) . "\n"; continue; } else { // grab but don't insert: $doInsert = false; } } if ($doInsert) { // insert: $dbw->insert('mv_stream_images', array('stream_id' => $MVStreams[$stream->name]->getStreamId(), 'time' => $relative_time)); $img_id = $dbw->insertId(); // $grab = exec('cd ' . $img_path . '; wget ' . $im_url); } if (is_file($local_img_file)) { echo "skipped {$local_img_file} \n"; continue; } // print "run copy: $metavid_img_url, $local_img_file \n"; if (!copy($metavid_img_url, $local_img_file)) { echo "failed to copy {$metavid_img_url} to {$local_img_file}...\n"; } else { // all good don't report anything' // print "all good\n"; } } }
/** * enables the rewriting of links to the Stream and Sequence namespace to support inline embeding. * see page: sample in-wiki-embed syntax * @@todo should probably be integrated to respective Stream and Sequence class. * and maybe integrated with File / image handle */ function mvLinkEnd($skin, $title, $options, &$text, &$attribs, &$ret) { global $mvDefaultAspectRatio, $mvDefaultVideoPlaybackRes, $mvEmbedKey; //only do link rewrites for $mvEmbedKey if (substr($title->getText(), 0, strlen($mvEmbedKey)) != $mvEmbedKey) { return true; } //parse text for extra parameters //@@todo integrate with image params / maybe file handle ) $params = explode('|', $text); //setup defaults: $size = $mvDefaultVideoPlaybackRes; $start_ntp = $end_ntp = null; foreach ($params as $param) { if (substr($param, -2) == 'px') { //size param if (strpos($param, 'x') === false) { $k = intval(str_replace($param, 'px', '')); //@@todo should use the actual clips aspect ratio $size = intval($v) . 'x' . (int) ($mvDefaultAspectRatio * $v); } else { list($width, $height) = explode('x', str_replace('px', '', $param)); $size = intval($width) . 'x' . intval($height); } } else { //only applicable to Stream: if ($title->getNamespace() == MV_NS_STREAM) { if (substr($param, 0, 6) == 'start=') { $start_str = substr($param, 6); $timeSec = npt2seconds($start_str); if ((int) $timeSec > 0) { $start_ntp = seconds2npt($timeSec); } } elseif (substr($param, 0, 4) == 'end=') { $end_str = substr($param, 6); $timeSec = npt2seconds($start_str); if ((int) $timeSec > 0) { $end_ntp = seconds2npt($timeSec); } } else { //caption text / desc } } } } if (substr($title->getText(), 0, strlen($mvEmbedKey)) == $mvEmbedKey) { $resourceTitle = Title::newFromText(substr($title->getText(), strlen($mvEmbedKey) + 1)); if ($resourceTitle->getNamespace() == MV_NS_STREAM) { $mvTitle = new MV_Title($resourceTitle); $ret = $mvTitle->getEmbedVideoHtml(array('size' => $size, 'showmeta' => true)); } if ($resourceTitle->getNamespace() == MV_NS_SEQUENCE) { $seqPlayer = new MV_SequencePlayer($resourceTitle); $ret = $seqPlayer->getEmbedSeqHtml(array('size' => $size)); } return false; } return true; }
function get_aligned_time_title(&$pData, $preFix = 'Anno_en', $stream) { $dbr = wfGetDB(DB_SLAVE); $mvd_rows = MV_Index::getMVDInRange($stream->getStreamId(), $pData['wiki_start_time'] - 120, $pData['wiki_end_time'] + 120, $mvd_type = 'Anno_en', $getText = false, $smw_properties = 'Speech_by'); $doSpeechInsert = true; foreach ($mvd_rows as $row) { if ($row->Speech_by) { if ($row->Speech_by == $pData['Spoken_by']) { print "match update existing: {$row->Speech_by} == " . $pData['Spoken_by'] . "\n"; $anno_title_str = $preFix . ':' . $stream->name . '/' . seconds2npt($row->start_time) . '/' . seconds2npt($row->end_time); return $anno_title_str; } else { print "\nno existing speech match:{$row->Speech_by} != " . $pData['Spoken_by'] . "\n\n"; } } } return false; }
function getHTML() { global $wgUser; $o = ''; $sk = $wgUser->getSkin(); $dbr = wfGetDB(DB_SLAVE); //if in overview mode don't print out the navigator: global $wgRequest; if ($wgRequest->getVal('view') == 'overview') { return ''; } // get all annotative layers $stream_id = $this->mv_interface->article->mvTitle->getStreamId(); $stream_name = $this->mv_interface->article->mvTitle->getStreamName(); $stream_time_req = $this->mv_interface->article->mvTitle->getTimeRequest(); $start_sec = $this->mv_interface->article->mvTitle->getStartTimeSeconds(); $duration_sec = $this->mv_interface->article->mvTitle->getDuration(); $end_sec = $this->mv_interface->article->mvTitle->getEndTimeSeconds(); // print "start $start_sec end:$end_sec \n "; foreach (array('prev', 'next') as $pntype) { if ($o != '') { $o .= ' '; } if ($pntype == 'prev') { if ($start_sec == 0) { continue; } $qstart = 0; $qend = $start_sec - 1; $orderby = 'end_time DESC'; } elseif ($pntype == 'next') { $qstart = $end_sec + 1; $qend = $duration_sec; $orderby = 'start_time ASC'; } // print "Qstart looking for $pntype:$qstart: ".seconds2npt($qstart) ." Qend:$qend : " . seconds2npt($qend) . " \n"; $mvd_rows = MV_Index::getMVDInRange($stream_id, $qstart, $qend, $mvd_type = 'anno_en', $getText = false, $smw_properties = array('Speech_by', 'Bill', 'category'), $options = array('LIMIT' => 1, 'ORDER BY' => $orderby)); //print $dbr->lastQuery(); //print_r($mvd_rows); //die; // print "SHOULD GET $pntype for $stream_time_req"; reset($mvd_rows); if (count($mvd_rows) != 0) { $row = current($mvd_rows); // $prev_end = $row->end_time; $stime_req = seconds2npt($row->start_time) . '/' . seconds2npt($row->end_time); $streamTitle = Title::newFromText($stream_name . '/' . $stime_req, MV_NS_STREAM); $tool_tip = ''; // print_r($row); if (isset($row->Speech_by)) { if (trim($row->Speech_by) != '') { //check if the person has an icon: $pimg = mv_get_person_img($row->Speech_by); $o .= wfMsg('mv_' . $pntype . '_speech', $sk->makeKnownLinkObj($streamTitle, '<img title="' . str_replace('_', ' ', $row->Speech_by) . '" width="40" src="' . $pimg->getURL() . '">')); //$o .= wfMsg( 'mv_' . $pntype . '_speech', $sk->makeKnownLinkObj( $streamTitle, str_replace( '_', ' ', $row->Speech_by ) ) ); // $tool_tip.= 'Speech By: '. $row->Speech_by; } elseif (trim($row->Bill) != '') { $o .= wfMsg('mv_' . $pntype . '_bill', $sk->makeKnownLinkObj($streamTitle, str_replace('_', ' ', $row->Bill))); } elseif (is_array($row->category) && count($row->category) != 0) { $first_cat = current($row->category); $o .= wfMsg('mv_' . $pntype . '_cat', $sk->makeKnownLinkObj($streamTitle, str_replace('_', ' ', $first_cat))); } } } } return $o; }
/** * returns a near by stream range: */ function getNearStreamName($range = null, $length = null) { global $mvDefaultClipLength, $mvDefaultClipRange; $stream =& mvGetMVStream($this->stream_name); if ($range === null) { $range = $mvDefaultClipRange; } if ($length === null) { $length = $mvDefaultClipLength; } // subtract $range seconds from the start time: $start_t = $this->getStartTimeSeconds() - $range; if ($start_t < 0) { $start_t = 0; } $start_ntp = seconds2npt($start_t); // add $range seconds to the end time: if (isset($this->end_time)) { $end_t = $this->getEndTimeSeconds() + $range; if ($end_t > $stream->getDuration()) { $end_t = $stream->getDuration(); } $end_ntp = '/' . seconds2npt($this->getEndTimeSeconds() + $range); } else { // make the end time the default Clip length $end_ntp = '/' . seconds2npt($this->getStartTimeSeconds() + $length + $range); } return $this->stream_name . '/' . $start_ntp . $end_ntp; }