Implement getRecordingTextTracks.

This commit is contained in:
Ghazi Triki 2019-05-01 16:14:10 +01:00
parent 35506cdc44
commit eef047d4e3
6 changed files with 123 additions and 82 deletions

View File

@ -54,6 +54,7 @@ public class RecordingService {
private String recordStatusDir;
private String captionsDir;
private String presentationBaseDir;
private String defaultServerUrl;
private void copyPresentationFile(File presFile, File dlownloadableFile) {
try {
@ -75,7 +76,7 @@ public class RecordingService {
copyPresentationFile(presFile, downloadableFile);
} else {
if (downloadableFile.exists()) {
if(downloadableFile.delete()) {
if (downloadableFile.delete()) {
log.info("File deleted. {}", downloadableFile.getAbsolutePath());
} else {
log.warn("Failed to delete. {}", downloadableFile.getAbsolutePath());
@ -86,7 +87,8 @@ public class RecordingService {
}
public File getDownloadablePresentationFile(String meetingId, String presId, String presFilename) {
log.info("Find downloadable presentation for meetingId={} presId={} filename={}", meetingId, presId, presFilename);
log.info("Find downloadable presentation for meetingId={} presId={} filename={}", meetingId, presId,
presFilename);
File presDir = Util.getPresentationDir(presentationBaseDir, meetingId, presId);
return new File(presDir.getAbsolutePath() + File.separatorChar + presFilename);
@ -169,7 +171,7 @@ public class RecordingService {
}
public String getRecordingTextTracks(String recordId) {
return recordingServiceHelper.getRecordingTextTracks(recordId, captionsDir);
return recordingServiceHelper.getRecordingTextTracks(recordId, captionsDir, getCaptionFileUrlDirectory(recordId));
}
public String putRecordingTextTrack(UploadedTrack track) {
@ -192,21 +194,24 @@ public class RecordingService {
Map<String, String> recMeta = recording.getMeta();
for (Map.Entry<String, String> filter : metadataFilters.entrySet()) {
String metadataValue = recMeta.get(filter.getKey());
if ( metadataValue == null ) {
if (metadataValue == null) {
// The recording doesn't have metadata specified
matchesMetadata = false;
} else {
String filterValue = filter.getValue();
if( filterValue.charAt(0) == '%' && filterValue.charAt(filterValue.length()-1) == '%' && metadataValue.contains(filterValue.substring(1, filterValue.length()-1)) ){
if (filterValue.charAt(0) == '%' && filterValue.charAt(filterValue.length() - 1) == '%'
&& metadataValue.contains(filterValue.substring(1, filterValue.length() - 1))) {
// Filter value embraced by two wild cards
// AND the filter value is part of the metadata value
} else if( filterValue.charAt(0) == '%' && metadataValue.endsWith(filterValue.substring(1, filterValue.length())) ) {
} else if (filterValue.charAt(0) == '%'
&& metadataValue.endsWith(filterValue.substring(1, filterValue.length()))) {
// Filter value starts with a wild cards
// AND the filter value ends with the metadata value
} else if( filterValue.charAt(filterValue.length()-1) == '%' && metadataValue.startsWith(filterValue.substring(0, filterValue.length()-1)) ) {
} else if (filterValue.charAt(filterValue.length() - 1) == '%'
&& metadataValue.startsWith(filterValue.substring(0, filterValue.length() - 1))) {
// Filter value ends with a wild cards
// AND the filter value starts with the metadata value
} else if( metadataValue.equals(filterValue) ) {
} else if (metadataValue.equals(filterValue)) {
// Filter value doesnt have wildcards
// AND the filter value is the same as metadata value
} else {
@ -217,8 +222,8 @@ public class RecordingService {
return matchesMetadata;
}
public ArrayList<RecordingMetadata> filterRecordingsByMetadata(List<RecordingMetadata> recordings, Map<String, String> metadataFilters) {
public ArrayList<RecordingMetadata> filterRecordingsByMetadata(List<RecordingMetadata> recordings,
Map<String, String> metadataFilters) {
ArrayList<RecordingMetadata> resultRecordings = new ArrayList<>();
for (RecordingMetadata entry : recordings) {
if (recordingMatchesMetadata(entry, metadataFilters))
@ -293,7 +298,7 @@ public class RecordingService {
while (iterator.hasNext()) {
File rec = iterator.next();
if (rec.getName().startsWith(id)) {
recs.add(rec);
recs.add(rec);
}
}
return recs;
@ -374,6 +379,10 @@ public class RecordingService {
presentationBaseDir = dir;
}
public void setDefaultServerUrl(String url) {
defaultServerUrl = url;
}
public void setPublishedDir(String dir) {
publishedDir = dir;
}
@ -435,24 +444,24 @@ public class RecordingService {
boolean exists = false;
boolean succeeded = true;
String[] format = getPlaybackFormats(path);
for (String aFormat : format) {
for (String aFormat : format) {
List<File> recordings = getDirectories(path + File.separatorChar + aFormat);
for (File recording : recordings) {
if (recording.getName().equalsIgnoreCase(recordingId)) {
exists = true;
File dest;
if (state.equals(Recording.STATE_PUBLISHED)) {
dest = new File(publishedDir + File.separatorChar + aFormat);
succeeded &= publishRecording(dest, recordingId, recording, aFormat);
dest = new File(publishedDir + File.separatorChar + aFormat);
succeeded &= publishRecording(dest, recordingId, recording, aFormat);
} else if (state.equals(Recording.STATE_UNPUBLISHED)) {
dest = new File(unpublishedDir + File.separatorChar + aFormat);
succeeded &= unpublishRecording(dest, recordingId, recording, aFormat);
dest = new File(unpublishedDir + File.separatorChar + aFormat);
succeeded &= unpublishRecording(dest, recordingId, recording, aFormat);
} else if (state.equals(Recording.STATE_DELETED)) {
dest = new File(deletedDir + File.separatorChar + aFormat);
succeeded &= deleteRecording(dest, recordingId, recording, aFormat);
dest = new File(deletedDir + File.separatorChar + aFormat);
succeeded &= deleteRecording(dest, recordingId, recording, aFormat);
} else {
log.debug(String.format("State: %s, is not supported", state));
return false;
log.debug(String.format("State: %s, is not supported", state));
return false;
}
}
}
@ -464,7 +473,8 @@ public class RecordingService {
File metadataXml = recordingServiceHelper.getMetadataXmlLocation(recordingDir.getPath());
RecordingMetadata r = recordingServiceHelper.getRecordingMetadata(metadataXml);
if (r != null) {
if (!destDir.exists()) destDir.mkdirs();
if (!destDir.exists())
destDir.mkdirs();
try {
FileUtils.moveDirectory(recordingDir, new File(destDir.getPath() + File.separatorChar + recordingId));
@ -472,13 +482,13 @@ public class RecordingService {
r.setState(Recording.STATE_PUBLISHED);
r.setPublished(true);
File medataXmlFile = recordingServiceHelper.getMetadataXmlLocation(
destDir.getAbsolutePath() + File.separatorChar + recordingId);
File medataXmlFile = recordingServiceHelper
.getMetadataXmlLocation(destDir.getAbsolutePath() + File.separatorChar + recordingId);
// Process the changes by saving the recording into metadata.xml
return recordingServiceHelper.saveRecordingMetadata(medataXmlFile, r);
} catch (IOException e) {
log.error("Failed to publish recording : " + recordingId, e);
log.error("Failed to publish recording : " + recordingId, e);
}
}
return false;
@ -489,20 +499,21 @@ public class RecordingService {
RecordingMetadata r = recordingServiceHelper.getRecordingMetadata(metadataXml);
if (r != null) {
if (!destDir.exists()) destDir.mkdirs();
if (!destDir.exists())
destDir.mkdirs();
try {
FileUtils.moveDirectory(recordingDir, new File(destDir.getPath() + File.separatorChar + recordingId));
r.setState(Recording.STATE_UNPUBLISHED);
r.setPublished(false);
File medataXmlFile = recordingServiceHelper.getMetadataXmlLocation(
destDir.getAbsolutePath() + File.separatorChar + recordingId);
File medataXmlFile = recordingServiceHelper
.getMetadataXmlLocation(destDir.getAbsolutePath() + File.separatorChar + recordingId);
// Process the changes by saving the recording into metadata.xml
return recordingServiceHelper.saveRecordingMetadata(medataXmlFile, r);
} catch (IOException e) {
log.error("Failed to unpublish recording : " + recordingId, e);
log.error("Failed to unpublish recording : " + recordingId, e);
}
}
return false;
@ -513,32 +524,32 @@ public class RecordingService {
RecordingMetadata r = recordingServiceHelper.getRecordingMetadata(metadataXml);
if (r != null) {
if (!destDir.exists()) destDir.mkdirs();
if (!destDir.exists())
destDir.mkdirs();
try {
FileUtils.moveDirectory(recordingDir, new File(destDir.getPath() + File.separatorChar + recordingId));
r.setState(Recording.STATE_DELETED);
r.setPublished(false);
File medataXmlFile = recordingServiceHelper.getMetadataXmlLocation(
destDir.getAbsolutePath() + File.separatorChar + recordingId);
File medataXmlFile = recordingServiceHelper
.getMetadataXmlLocation(destDir.getAbsolutePath() + File.separatorChar + recordingId);
// Process the changes by saving the recording into metadata.xml
return recordingServiceHelper.saveRecordingMetadata(medataXmlFile, r);
} catch (IOException e) {
log.error("Failed to delete recording : " + recordingId, e);
log.error("Failed to delete recording : " + recordingId, e);
}
}
return false;
}
private List<File> getAllDirectories(String state) {
List<File> allDirectories = new ArrayList<>();
String dir = getDestinationBaseDirectoryName(state);
if ( dir != null ) {
if (dir != null) {
String[] formats = getPlaybackFormats(dir);
for (String format : formats) {
allDirectories.addAll(getDirectories(dir + File.separatorChar + format));
@ -551,27 +562,27 @@ public class RecordingService {
private Map<String, List<File>> getAllDirectories(List<String> states) {
Map<String, List<File>> allDirectories = new HashMap<>();
if ( shouldIncludeState(states, Recording.STATE_PUBLISHED) ) {
if (shouldIncludeState(states, Recording.STATE_PUBLISHED)) {
List<File> listedDirectories = getAllDirectories(Recording.STATE_PUBLISHED);
allDirectories.put(Recording.STATE_PUBLISHED, listedDirectories);
}
if ( shouldIncludeState(states, Recording.STATE_UNPUBLISHED) ) {
if (shouldIncludeState(states, Recording.STATE_UNPUBLISHED)) {
List<File> listedDirectories = getAllDirectories(Recording.STATE_UNPUBLISHED);
allDirectories.put(Recording.STATE_UNPUBLISHED, listedDirectories);
}
if ( shouldIncludeState(states, Recording.STATE_DELETED) ) {
if (shouldIncludeState(states, Recording.STATE_DELETED)) {
List<File> listedDirectories = getAllDirectories(Recording.STATE_DELETED);
allDirectories.put(Recording.STATE_DELETED, listedDirectories);
}
if ( shouldIncludeState(states, Recording.STATE_PROCESSING) ) {
if (shouldIncludeState(states, Recording.STATE_PROCESSING)) {
List<File> listedDirectories = getAllDirectories(Recording.STATE_PROCESSING);
allDirectories.put(Recording.STATE_PROCESSING, listedDirectories);
}
if ( shouldIncludeState(states, Recording.STATE_PROCESSED) ) {
if (shouldIncludeState(states, Recording.STATE_PROCESSED)) {
List<File> listedDirectories = getAllDirectories(Recording.STATE_PROCESSED);
allDirectories.put(Recording.STATE_PROCESSED, listedDirectories);
}
@ -579,17 +590,19 @@ public class RecordingService {
return allDirectories;
}
public void updateMetaParams(List<String> recordIDs, Map<String,String> metaParams) {
public void updateMetaParams(List<String> recordIDs, Map<String, String> metaParams) {
// Define the directories used to lookup the recording
List<String> states = new ArrayList<>();
states.add(Recording.STATE_PUBLISHED);
states.add(Recording.STATE_UNPUBLISHED);
states.add(Recording.STATE_DELETED);
// Gather all the existent directories based on the states defined for the lookup
// Gather all the existent directories based on the states defined for
// the lookup
Map<String, List<File>> allDirectories = getAllDirectories(states);
// Retrieve the actual recording from the directories gathered for the lookup
// Retrieve the actual recording from the directories gathered for the
// lookup
for (String recordID : recordIDs) {
for (Map.Entry<String, List<File>> entry : allDirectories.entrySet()) {
List<File> recs = getRecordingsForPath(recordID, entry.getValue());
@ -603,19 +616,20 @@ public class RecordingService {
}
}
public void updateRecordingMetadata(File srxMetadataXml, Map<String,String> metaParams, File destMetadataXml) {
public void updateRecordingMetadata(File srxMetadataXml, Map<String, String> metaParams, File destMetadataXml) {
RecordingMetadata rec = recordingServiceHelper.getRecordingMetadata(srxMetadataXml);
Map<String, String> recMeta = rec.getMeta();
if (rec != null && !recMeta.isEmpty()) {
for (Map.Entry<String,String> meta : metaParams.entrySet()) {
if ( !"".equals(meta.getValue()) ) {
// As it has a value, if the meta parameter exists update it, otherwise add it
for (Map.Entry<String, String> meta : metaParams.entrySet()) {
if (!"".equals(meta.getValue())) {
// As it has a value, if the meta parameter exists update
// it, otherwise add it
recMeta.put(meta.getKey(), meta.getValue());
} else {
// As it doesn't have a value, if it exists delete it
if ( recMeta.containsKey(meta.getKey()) ) {
if (recMeta.containsKey(meta.getKey())) {
recMeta.remove(meta.getKey());
}
}
@ -628,9 +642,8 @@ public class RecordingService {
}
}
private Map<String,File> indexRecordings(List<File> recs) {
Map<String,File> indexedRecs = new HashMap<>();
private Map<String, File> indexRecordings(List<File> recs) {
Map<String, File> indexedRecs = new HashMap<>();
Iterator<File> iterator = recs.iterator();
while (iterator.hasNext()) {
@ -648,21 +661,26 @@ public class RecordingService {
private String getDestinationBaseDirectoryName(String state, boolean forceDefault) {
String baseDir = null;
if ( state.equals(Recording.STATE_PROCESSING) || state.equals(Recording.STATE_PROCESSED) )
if (state.equals(Recording.STATE_PROCESSING) || state.equals(Recording.STATE_PROCESSED))
baseDir = processDir;
else if ( state.equals(Recording.STATE_PUBLISHED) )
else if (state.equals(Recording.STATE_PUBLISHED))
baseDir = publishedDir;
else if ( state.equals(Recording.STATE_UNPUBLISHED) )
else if (state.equals(Recording.STATE_UNPUBLISHED))
baseDir = unpublishedDir;
else if ( state.equals(Recording.STATE_DELETED) )
else if (state.equals(Recording.STATE_DELETED))
baseDir = deletedDir;
else if ( forceDefault )
else if (forceDefault)
baseDir = publishedDir;
return baseDir;
}
public String getCaptionTrackInboxDir() {
return captionsDir + File.separatorChar + "inbox";
}
public String getCaptionTrackInboxDir() {
return captionsDir + File.separatorChar + "inbox";
}
public String getCaptionFileUrlDirectory(String recordId) {
return defaultServerUrl + "/captions/" + recordId + "/";
}
}

View File

@ -16,8 +16,8 @@ public class RecordingMetadataReaderHelper {
private RecordingServiceGW recordingServiceGW;
public String getRecordingTextTracks(String recordId, String captionsDir) {
return recordingServiceGW.getRecordingTextTracks(recordId, captionsDir);
public String getRecordingTextTracks(String recordId, String captionsDir, String captionsBaseUrl) {
return recordingServiceGW.getRecordingTextTracks(recordId, captionsDir, captionsBaseUrl);
}
public String putRecordingTextTrack(UploadedTrack track) {

View File

@ -13,6 +13,6 @@ public interface RecordingServiceGW {
String getRecordings2x(ArrayList<RecordingMetadata> recs);
Option<RecordingMetadata> getRecordingMetadata(File xml);
boolean saveRecordingMetadata(File xml, RecordingMetadata metadata);
String getRecordingTextTracks(String recordId, String captionsDir);
String getRecordingTextTracks(String recordId, String captionsDir, String captionBasUrl);
String putRecordingTextTrack(UploadedTrack track);
}

View File

@ -20,7 +20,9 @@ import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Paths
class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
import com.google.gson.internal.LinkedTreeMap
class RecordingMetaXmlHelper extends RecordingServiceGW with LogHelper {
val SUCCESS = "SUCCESS"
val FAILED = "FAILED"
@ -131,7 +133,8 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
case None => ListBuffer()
},
recMeta.breakout,
recMeta.breakoutRooms)
recMeta.breakoutRooms
)
recMetaResponse
}
@ -187,17 +190,33 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
}
}
def getRecordingTextTracks(recordId: String, captionsDir: String): String = {
def getRecordingTextTracks(recordId: String, captionsDir: String, captionBasUrl: String): String = {
val gson = new Gson()
var returnResponse: String = ""
val captionsFilePath = captionsDir + File.separatorChar + recordId + File.separatorChar + CAPTIONS_FILE
readCaptionJsonFile(captionsFilePath, StandardCharsets.UTF_8) match {
case Some(captions) =>
val ctracks = gson.fromJson(captions, classOf[util.ArrayList[Track]])
val textTracksResult = GetRecTextTracksResult(SUCCESS, ctracks)
val ctracks = gson.fromJson(captions, classOf[java.util.List[LinkedTreeMap[String, String]]])
val list = new util.ArrayList[Track]()
val it = ctracks.iterator()
while (it.hasNext()) {
val mapTrack = it.next()
list.add(new Track(
href = captionBasUrl + mapTrack.get("lang") + ".json",
kind = mapTrack.get("kind"),
label = mapTrack.get("label"),
lang = mapTrack.get("lang"),
source = mapTrack.get("source")
))
}
val textTracksResult = GetRecTextTracksResult(SUCCESS, list)
val textTracksResponse = GetRecTextTracksResp(textTracksResult)
val textTracksJson = gson.toJson(textTracksResponse)
// parse(textTracksJson).transformField{case JField(x, v) if x == "value" && v == JString("Company")=> JField("value1",JString("Company1"))}
returnResponse = textTracksJson
case None =>
@ -261,7 +280,8 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
kind = track.kind,
lang = track.lang,
label = track.label,
origFilename = track.origFilename)
origFilename = track.origFilename
)
val gson = new Gson()
val trackInfoJson = gson.toJson(trackInfo)
@ -271,7 +291,8 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
SUCCESS,
track.recordId,
messageKey = "upload_text_track_success",
message = "Text track uploaded successfully")
message = "Text track uploaded successfully"
)
val resp = PutRecTextTrackResp(result)
gson.toJson(resp)
} else {
@ -279,7 +300,8 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
FAILED,
track.recordId,
messageKey = "upload_text_track_failed",
message = "Text track upload failed.")
message = "Text track upload failed."
)
val resp = PutRecTextTrackResp(result)
gson.toJson(resp)
}

View File

@ -3,19 +3,19 @@ package org.bigbluebutton.api2.util
import org.bigbluebutton.api.util.UnitSpec
import org.bigbluebutton.api2.domain.RecMeta
class RecMetaXmlHelperTests extends UnitSpec {
class RecordingMetaXmlHelperTests extends UnitSpec {
val metaFile = "src/test/resources/sample-metadata.xml"
it should "load metadata xml" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
// println("METADATAXML = \n" + xml)
}
it should "get meta elements" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -30,7 +30,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get meeting element" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -46,7 +46,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get playback element" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -62,7 +62,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get extensions" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -77,7 +77,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get breakout rooms" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -91,7 +91,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get breakout" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -104,7 +104,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get recording metadata" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -118,7 +118,7 @@ class RecMetaXmlHelperTests extends UnitSpec {
}
it should "get recording metadata and format back to metadata" in {
val helper = new RecMetaXmlHelper
val helper = new RecordingMetaXmlHelper
val xml = helper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
@ -133,10 +133,10 @@ class RecMetaXmlHelperTests extends UnitSpec {
/*
it should "get copy meta" in {
val xml = RecMetaXmlHelper.loadMetadataXml(metaFile)
val xml = RecordingMetaXmlHelper.loadMetadataXml(metaFile)
xml match {
case Some(metaXml) =>
RecMetaXmlHelper.getMetaCopy(metaXml) match {
RecordingMetaXmlHelper.getMetaCopy(metaXml) match {
case Some(br) =>
println(br)
assert(true)

View File

@ -66,7 +66,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<property name="recordingServiceGW" ref="recordingServiceGW"/>
</bean>
<bean id="recordingServiceGW" class="org.bigbluebutton.api2.util.RecMetaXmlHelper">
<bean id="recordingServiceGW" class="org.bigbluebutton.api2.util.RecordingMetaXmlHelper">
</bean>
<bean id="presDownloadService" class="org.bigbluebutton.presentation.PresentationUrlDownloadService"
@ -85,6 +85,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<property name="captionsDir" value="${captionsDir}"/>
<property name="recordingServiceHelper" ref="recordingServiceHelper"/>
<property name="presentationBaseDir" value="${presentationDir}"/>
<property name="defaultServerUrl" value="${bigbluebutton.web.serverURL}"/>
</bean>
<bean id="configServiceHelper" class="org.bigbluebutton.api.ClientConfigServiceHelperImp"/>