use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.
the class IBMWatsonTranscriptionService method getGeneratedTranscription.
@Override
public MediaPackageElement getGeneratedTranscription(String mpId, String jobId) throws TranscriptionServiceException {
try {
// If jobId is unknown, look for all jobs associated to that mpId
if (jobId == null || "null".equals(jobId)) {
jobId = null;
for (TranscriptionJobControl jc : database.findByMediaPackage(mpId)) {
if (TranscriptionJobControl.Status.Closed.name().equals(jc.getStatus()) || TranscriptionJobControl.Status.TranscriptionComplete.name().equals(jc.getStatus()))
jobId = jc.getTranscriptionJobId();
}
}
if (jobId == null)
throw new TranscriptionServiceException("No completed or closed transcription job found in database for media package " + mpId);
// Results already saved?
URI uri = workspace.getCollectionURI(TRANSCRIPT_COLLECTION, buildResultsFileName(jobId));
try {
workspace.get(uri);
} catch (Exception e) {
// Not saved yet so call the ibm watson service to get the results
getAndSaveJobResults(jobId);
}
MediaPackageElementBuilder builder = MediaPackageElementBuilderFactory.newInstance().newElementBuilder();
return builder.elementFromURI(uri, Attachment.TYPE, new MediaPackageElementFlavor("captions", "ibm-watson-json"));
} catch (TranscriptionDatabaseException e) {
throw new TranscriptionServiceException("Job id not informed and could not find transcription", e);
}
}
use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.
the class ThemeWorkflowOperationHandler method start.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance,
* JobContext)
*/
@Override
public WorkflowOperationResult start(final WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
logger.debug("Running theme workflow operation on workflow {}", workflowInstance.getId());
final MediaPackageElementFlavor bumperFlavor = getOptConfig(workflowInstance, BUMPER_FLAVOR).map(toMediaPackageElementFlavor).getOr(new MediaPackageElementFlavor("branding", "bumper"));
final MediaPackageElementFlavor trailerFlavor = getOptConfig(workflowInstance, TRAILER_FLAVOR).map(toMediaPackageElementFlavor).getOr(new MediaPackageElementFlavor("branding", "trailer"));
final MediaPackageElementFlavor titleSlideFlavor = getOptConfig(workflowInstance, TITLE_SLIDE_FLAVOR).map(toMediaPackageElementFlavor).getOr(new MediaPackageElementFlavor("branding", "title-slide"));
final MediaPackageElementFlavor licenseSlideFlavor = getOptConfig(workflowInstance, LICENSE_SLIDE_FLAVOR).map(toMediaPackageElementFlavor).getOr(new MediaPackageElementFlavor("branding", "license-slide"));
final MediaPackageElementFlavor watermarkFlavor = getOptConfig(workflowInstance, WATERMARK_FLAVOR).map(toMediaPackageElementFlavor).getOr(new MediaPackageElementFlavor("branding", "watermark"));
final List<String> bumperTags = asList(workflowInstance.getConfiguration(BUMPER_TAGS));
final List<String> trailerTags = asList(workflowInstance.getConfiguration(TRAILER_TAGS));
final List<String> titleSlideTags = asList(workflowInstance.getConfiguration(TITLE_SLIDE_TAGS));
final List<String> licenseSlideTags = asList(workflowInstance.getConfiguration(LICENSE_SLIDE_TAGS));
final List<String> watermarkTags = asList(workflowInstance.getConfiguration(WATERMARK_TAGS));
Opt<String> layoutStringOpt = getOptConfig(workflowInstance, WATERMARK_LAYOUT);
Opt<String> watermarkLayoutVariable = getOptConfig(workflowInstance, WATERMARK_LAYOUT_VARIABLE);
List<String> layoutList = new ArrayList<>(Stream.$(layoutStringOpt).bind(Strings.split(";")).toList());
try {
MediaPackage mediaPackage = workflowInstance.getMediaPackage();
String series = mediaPackage.getSeries();
if (series == null) {
logger.info("Skipping theme workflow operation, no series assigned to mediapackage {}", mediaPackage.getIdentifier());
return createResult(Action.SKIP);
}
Long themeId;
try {
themeId = Long.parseLong(seriesService.getSeriesProperty(series, THEME_PROPERTY_NAME));
} catch (NotFoundException e) {
logger.info("Skipping theme workflow operation, no theme assigned to series {} on mediapackage {}.", series, mediaPackage.getIdentifier());
return createResult(Action.SKIP);
} catch (UnauthorizedException e) {
logger.warn("Skipping theme workflow operation, user not authorized to perform operation: {}", ExceptionUtils.getStackTrace(e));
return createResult(Action.SKIP);
}
Theme theme;
try {
theme = themesServiceDatabase.getTheme(themeId);
} catch (NotFoundException e) {
logger.warn("Skipping theme workflow operation, no theme with id {} found.", themeId);
return createResult(Action.SKIP);
}
logger.info("Applying theme {} to mediapackage {}", themeId, mediaPackage.getIdentifier());
/* Make theme settings available to workflow instance */
workflowInstance.setConfiguration(THEME_ACTIVE, Boolean.toString(theme.isBumperActive() || theme.isTrailerActive() || theme.isTitleSlideActive() || theme.isWatermarkActive()));
workflowInstance.setConfiguration(THEME_BUMPER_ACTIVE, Boolean.toString(theme.isBumperActive()));
workflowInstance.setConfiguration(THEME_TRAILER_ACTIVE, Boolean.toString(theme.isTrailerActive()));
workflowInstance.setConfiguration(THEME_TITLE_SLIDE_ACTIVE, Boolean.toString(theme.isTitleSlideActive()));
workflowInstance.setConfiguration(THEME_TITLE_SLIDE_UPLOADED, Boolean.toString(StringUtils.isNotBlank(theme.getTitleSlideBackground())));
workflowInstance.setConfiguration(THEME_WATERMARK_ACTIVE, Boolean.toString(theme.isWatermarkActive()));
if (theme.isBumperActive() && StringUtils.isNotBlank(theme.getBumperFile())) {
try (InputStream bumper = staticFileService.getFile(theme.getBumperFile())) {
addElement(mediaPackage, bumperFlavor, bumperTags, bumper, staticFileService.getFileName(theme.getBumperFile()), Type.Track);
} catch (NotFoundException e) {
logger.warn("Bumper file {} not found in static file service, skip applying it", theme.getBumperFile());
}
}
if (theme.isTrailerActive() && StringUtils.isNotBlank(theme.getTrailerFile())) {
try (InputStream trailer = staticFileService.getFile(theme.getTrailerFile())) {
addElement(mediaPackage, trailerFlavor, trailerTags, trailer, staticFileService.getFileName(theme.getTrailerFile()), Type.Track);
} catch (NotFoundException e) {
logger.warn("Trailer file {} not found in static file service, skip applying it", theme.getTrailerFile());
}
}
if (theme.isTitleSlideActive()) {
if (StringUtils.isNotBlank(theme.getTitleSlideBackground())) {
try (InputStream titleSlideBackground = staticFileService.getFile(theme.getTitleSlideBackground())) {
addElement(mediaPackage, titleSlideFlavor, titleSlideTags, titleSlideBackground, staticFileService.getFileName(theme.getTitleSlideBackground()), Type.Attachment);
} catch (NotFoundException e) {
logger.warn("Title slide file {} not found in static file service, skip applying it", theme.getTitleSlideBackground());
}
}
// TODO add the title slide metadata to the workflow properties to be used by the cover-image WOH
// String titleSlideMetadata = theme.getTitleSlideMetadata();
}
if (theme.isLicenseSlideActive()) {
if (StringUtils.isNotBlank(theme.getLicenseSlideBackground())) {
try (InputStream licenseSlideBackground = staticFileService.getFile(theme.getLicenseSlideBackground())) {
addElement(mediaPackage, licenseSlideFlavor, licenseSlideTags, licenseSlideBackground, staticFileService.getFileName(theme.getLicenseSlideBackground()), Type.Attachment);
} catch (NotFoundException e) {
logger.warn("License slide file {} not found in static file service, skip applying it", theme.getLicenseSlideBackground());
}
} else {
// TODO define what to do here (maybe extract image as background)
}
// TODO add the license slide description to the workflow properties to be used by the cover-image WOH
// String licenseSlideDescription = theme.getLicenseSlideDescription();
}
if (theme.isWatermarkActive() && StringUtils.isNotBlank(theme.getWatermarkFile())) {
try (InputStream watermark = staticFileService.getFile(theme.getWatermarkFile())) {
addElement(mediaPackage, watermarkFlavor, watermarkTags, watermark, staticFileService.getFileName(theme.getWatermarkFile()), Type.Attachment);
} catch (NotFoundException e) {
logger.warn("Watermark file {} not found in static file service, skip applying it", theme.getWatermarkFile());
}
if (layoutStringOpt.isNone() || watermarkLayoutVariable.isNone())
throw new WorkflowOperationException(format("Configuration key '%s' or '%s' is either missing or empty", WATERMARK_LAYOUT, WATERMARK_LAYOUT_VARIABLE));
AbsolutePositionLayoutSpec watermarkLayout = parseLayout(theme.getWatermarkPosition());
layoutList.set(layoutList.size() - 1, Serializer.json(watermarkLayout).toJson());
layoutStringOpt = Opt.some(Stream.$(layoutList).mkString(";"));
}
if (watermarkLayoutVariable.isSome() && layoutStringOpt.isSome())
workflowInstance.setConfiguration(watermarkLayoutVariable.get(), layoutStringOpt.get());
return createResult(mediaPackage, Action.CONTINUE);
} catch (SeriesException | ThemesServiceDatabaseException | IllegalStateException | IllegalArgumentException | IOException e) {
throw new WorkflowOperationException(e);
}
}
use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.
the class AttachTranscriptionOperationHandler method start.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance,
* JobContext)
*/
@Override
public WorkflowOperationResult start(final WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
MediaPackage mediaPackage = workflowInstance.getMediaPackage();
WorkflowOperationInstance operation = workflowInstance.getCurrentOperation();
logger.debug("Attach transcription for mediapackage {} started", mediaPackage);
// Get job id.
String jobId = StringUtils.trimToNull(operation.getConfiguration(TRANSCRIPTION_JOB_ID));
if (jobId == null)
throw new WorkflowOperationException(TRANSCRIPTION_JOB_ID + " missing");
// Check which tags/flavors have been configured
String targetTagOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_TAG));
String targetFlavorOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_FLAVOR));
String captionFormatOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_CAPTION_FORMAT));
// Target flavor is mandatory if target-caption-format was NOT informed and no conversion is done
if (targetFlavorOption == null && captionFormatOption == null)
throw new WorkflowOperationException(TARGET_FLAVOR + " missing");
// Target flavor is optional if target-caption-format was informed because the default flavor
// will be "captions/<format>". If informed, will override the default.
MediaPackageElementFlavor flavor = null;
if (targetFlavorOption != null)
flavor = MediaPackageElementFlavor.parseFlavor(targetFlavorOption);
try {
// Get transcription file from the service
MediaPackageElement original = service.getGeneratedTranscription(mediaPackage.getIdentifier().compact(), jobId);
MediaPackageElement transcription = original;
// If caption format passed, convert to desired format
if (captionFormatOption != null) {
Job job = captionService.convert(transcription, "ibm-watson", captionFormatOption, service.getLanguage());
if (!waitForStatus(job).isSuccess()) {
throw new WorkflowOperationException("Transcription format conversion job did not complete successfully");
}
transcription = MediaPackageElementParser.getFromXml(job.getPayload());
}
// Set the target flavor if informed
if (flavor != null)
transcription.setFlavor(flavor);
// Add tags
if (targetTagOption != null) {
for (String tag : asList(targetTagOption)) {
if (StringUtils.trimToNull(tag) != null)
transcription.addTag(tag);
}
}
// Add to media package
mediaPackage.add(transcription);
String uri = transcription.getURI().toString();
String ext = uri.substring(uri.lastIndexOf("."));
transcription.setURI(workspace.moveTo(transcription.getURI(), mediaPackage.getIdentifier().toString(), transcription.getIdentifier(), "captions." + ext));
} catch (Exception e) {
throw new WorkflowOperationException(e);
}
return createResult(mediaPackage, Action.CONTINUE);
}
use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.
the class PublicationBuilderPlugin method elementFromManifest.
@Override
public MediaPackageElement elementFromManifest(Node elementNode, MediaPackageSerializer serializer) throws UnsupportedElementException {
String id = null;
MimeType mimeType = null;
MediaPackageElementFlavor flavor = null;
String reference = null;
String channel = null;
URI url = null;
long size = -1;
Checksum checksum = null;
try {
// id
id = (String) xpath.evaluate("@id", elementNode, XPathConstants.STRING);
if (StringUtils.isEmpty(id)) {
throw new UnsupportedElementException("Unvalid or missing id argument!");
}
// url
url = serializer.decodeURI(new URI(xpath.evaluate("url/text()", elementNode).trim()));
// channel
channel = xpath.evaluate("@channel", elementNode).trim();
if (StringUtils.isEmpty(channel)) {
throw new UnsupportedElementException("Unvalid or missing channel argument!");
}
// reference
reference = (String) xpath.evaluate("@ref", elementNode, XPathConstants.STRING);
// size
String trackSize = xpath.evaluate("size/text()", elementNode).trim();
if (!"".equals(trackSize))
size = Long.parseLong(trackSize);
// flavor
String flavorValue = (String) xpath.evaluate("@type", elementNode, XPathConstants.STRING);
if (StringUtils.isNotEmpty(flavorValue))
flavor = MediaPackageElementFlavor.parseFlavor(flavorValue);
// checksum
String checksumValue = (String) xpath.evaluate("checksum/text()", elementNode, XPathConstants.STRING);
String checksumType = (String) xpath.evaluate("checksum/@type", elementNode, XPathConstants.STRING);
if (StringUtils.isNotEmpty(checksumValue) && checksumType != null)
checksum = Checksum.create(checksumType.trim(), checksumValue.trim());
// mimetype
String mimeTypeValue = (String) xpath.evaluate("mimetype/text()", elementNode, XPathConstants.STRING);
if (StringUtils.isNotEmpty(mimeTypeValue)) {
mimeType = MimeTypes.parseMimeType(mimeTypeValue);
} else {
throw new UnsupportedElementException("Unvalid or missing mimetype argument!");
}
// Build the publication element
PublicationImpl publication = new PublicationImpl(id, channel, url, mimeType);
if (StringUtils.isNotBlank(id))
publication.setIdentifier(id);
// Add url
publication.setURI(url);
// Add reference
if (StringUtils.isNotEmpty(reference))
publication.referTo(MediaPackageReferenceImpl.fromString(reference));
// Set size
if (size > 0)
publication.setSize(size);
// Set checksum
if (checksum != null)
publication.setChecksum(checksum);
// Set mimetpye
if (mimeType != null)
publication.setMimeType(mimeType);
if (flavor != null)
publication.setFlavor(flavor);
// description
String description = (String) xpath.evaluate("description/text()", elementNode, XPathConstants.STRING);
if (StringUtils.isNotBlank(description))
publication.setElementDescription(description.trim());
// tags
NodeList tagNodes = (NodeList) xpath.evaluate("tags/tag", elementNode, XPathConstants.NODESET);
for (int i = 0; i < tagNodes.getLength(); i++) {
publication.addTag(tagNodes.item(i).getTextContent());
}
return publication;
} catch (XPathExpressionException e) {
throw new UnsupportedElementException("Error while reading track information from manifest: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedElementException("Unsupported digest algorithm: " + e.getMessage());
} catch (URISyntaxException e) {
throw new UnsupportedElementException("Error while reading presenter track " + url + ": " + e.getMessage());
}
}
use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.
the class ExecuteManyWorkflowOperationHandler method start.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance,
* JobContext)
*/
@Override
public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
MediaPackage mediaPackage = workflowInstance.getMediaPackage();
WorkflowOperationInstance operation = workflowInstance.getCurrentOperation();
logger.debug("Running execute workflow operation with ID {}", operation.getId());
// Get operation parameters
String exec = StringUtils.trimToNull(operation.getConfiguration(EXEC_PROPERTY));
String params = StringUtils.trimToNull(operation.getConfiguration(PARAMS_PROPERTY));
float load = 1.0f;
String loadPropertyStr = StringUtils.trimToEmpty(operation.getConfiguration(LOAD_PROPERTY));
if (StringUtils.isNotBlank(loadPropertyStr)) {
try {
load = Float.parseFloat(loadPropertyStr);
} catch (NumberFormatException e) {
String description = StringUtils.trimToEmpty(operation.getDescription());
logger.warn("Ignoring invalid load value '{}' on execute operation with description '{}'", loadPropertyStr, description);
}
}
String sourceFlavor = StringUtils.trimToNull(operation.getConfiguration(SOURCE_FLAVOR_PROPERTY));
String sourceTags = StringUtils.trimToNull(operation.getConfiguration(SOURCE_TAGS_PROPERTY));
String targetFlavorStr = StringUtils.trimToNull(operation.getConfiguration(TARGET_FLAVOR_PROPERTY));
String targetTags = StringUtils.trimToNull(operation.getConfiguration(TARGET_TAGS_PROPERTY));
String outputFilename = StringUtils.trimToNull(operation.getConfiguration(OUTPUT_FILENAME_PROPERTY));
String expectedTypeStr = StringUtils.trimToNull(operation.getConfiguration(EXPECTED_TYPE_PROPERTY));
MediaPackageElementFlavor matchingFlavor = null;
if (sourceFlavor != null)
matchingFlavor = MediaPackageElementFlavor.parseFlavor(sourceFlavor);
// Unmarshall target flavor
MediaPackageElementFlavor targetFlavor = null;
if (targetFlavorStr != null)
targetFlavor = MediaPackageElementFlavor.parseFlavor(targetFlavorStr);
// Unmarshall expected mediapackage element type
MediaPackageElement.Type expectedType = null;
if (expectedTypeStr != null) {
for (MediaPackageElement.Type type : MediaPackageElement.Type.values()) if (type.toString().equalsIgnoreCase(expectedTypeStr)) {
expectedType = type;
break;
}
if (expectedType == null)
throw new WorkflowOperationException("'" + expectedTypeStr + "' is not a valid element type");
}
List<String> sourceTagList = asList(sourceTags);
// Select the tracks based on source flavors and tags
Set<MediaPackageElement> inputSet = new HashSet<>();
for (MediaPackageElement element : mediaPackage.getElementsByTags(sourceTagList)) {
MediaPackageElementFlavor elementFlavor = element.getFlavor();
if (sourceFlavor == null || (elementFlavor != null && elementFlavor.matches(matchingFlavor))) {
inputSet.add(element);
}
}
if (inputSet.size() == 0) {
logger.warn("Mediapackage {} has no suitable elements to execute the command {} based on tags {} and flavor {}", mediaPackage, exec, sourceTags, sourceFlavor);
return createResult(mediaPackage, Action.CONTINUE);
}
MediaPackageElement[] inputElements = inputSet.toArray(new MediaPackageElement[inputSet.size()]);
try {
Job[] jobs = new Job[inputElements.length];
MediaPackageElement[] resultElements = new MediaPackageElement[inputElements.length];
long totalTimeInQueue = 0;
for (int i = 0; i < inputElements.length; i++) jobs[i] = executeService.execute(exec, params, inputElements[i], outputFilename, expectedType, load);
// Wait for all jobs to be finished
if (!waitForStatus(jobs).isSuccess())
throw new WorkflowOperationException("Execute operation failed");
// Find which output elements are tracks and inspect them
HashMap<Integer, Job> jobMap = new HashMap<>();
for (int i = 0; i < jobs.length; i++) {
// Add this job's queue time to the total
totalTimeInQueue += jobs[i].getQueueTime();
if (StringUtils.trimToNull(jobs[i].getPayload()) != null) {
resultElements[i] = MediaPackageElementParser.getFromXml(jobs[i].getPayload());
if (resultElements[i].getElementType() == MediaPackageElement.Type.Track) {
jobMap.put(i, inspectionService.inspect(resultElements[i].getURI()));
}
} else
resultElements[i] = inputElements[i];
}
if (jobMap.size() > 0) {
if (!waitForStatus(jobMap.values().toArray(new Job[jobMap.size()])).isSuccess())
throw new WorkflowOperationException("Execute operation failed in track inspection");
for (Entry<Integer, Job> entry : jobMap.entrySet()) {
// Add this job's queue time to the total
totalTimeInQueue += entry.getValue().getQueueTime();
resultElements[entry.getKey()] = MediaPackageElementParser.getFromXml(entry.getValue().getPayload());
}
}
for (int i = 0; i < resultElements.length; i++) {
if (resultElements[i] != inputElements[i]) {
// Store new element to mediaPackage
mediaPackage.addDerived(resultElements[i], inputElements[i]);
// Store new element to mediaPackage
URI uri = workspace.moveTo(resultElements[i].getURI(), mediaPackage.getIdentifier().toString(), resultElements[i].getIdentifier(), outputFilename);
resultElements[i].setURI(uri);
// Set new flavor
if (targetFlavor != null)
resultElements[i].setFlavor(targetFlavor);
}
// Set new tags
if (targetTags != null) {
// Assume the tags starting with "-" means we want to eliminate such tags form the result element
for (String tag : asList(targetTags)) {
if (tag.startsWith("-"))
// We remove the tag resulting from stripping all the '-' characters at the beginning of the tag
resultElements[i].removeTag(tag.replaceAll("^-+", ""));
else
resultElements[i].addTag(tag);
}
}
}
WorkflowOperationResult result = createResult(mediaPackage, Action.CONTINUE, totalTimeInQueue);
logger.debug("Execute operation {} completed", operation.getId());
return result;
} catch (ExecuteException e) {
throw new WorkflowOperationException(e);
} catch (MediaPackageException e) {
throw new WorkflowOperationException("Some result element couldn't be serialized", e);
} catch (NotFoundException e) {
throw new WorkflowOperationException("Could not find mediapackage", e);
} catch (IOException e) {
throw new WorkflowOperationException("Error unmarshalling a result mediapackage element", e);
} catch (MediaInspectionException e) {
throw new WorkflowOperationException("Error inspecting one of the created tracks", e);
}
}
Aggregations