Search in sources :

Example 26 with WorkflowOperationException

use of org.opencastproject.workflow.api.WorkflowOperationException in project opencast by opencast.

the class ConcatWorkflowOperationHandler method getTrackSelectors.

private Map<Integer, Tuple<TrackSelector, Boolean>> getTrackSelectors(WorkflowOperationInstance operation) throws WorkflowOperationException {
    Map<Integer, Tuple<TrackSelector, Boolean>> trackSelectors = new HashMap<Integer, Tuple<TrackSelector, Boolean>>();
    for (String key : operation.getConfigurationKeys()) {
        String tags = null;
        String flavor = null;
        Boolean mandatory = true;
        int number = -1;
        if (key.startsWith(SOURCE_TAGS_PREFIX) && !key.endsWith(MANDATORY_SUFFIX)) {
            number = NumberUtils.toInt(key.substring(SOURCE_TAGS_PREFIX.length()), -1);
            tags = operation.getConfiguration(key);
            mandatory = BooleanUtils.toBooleanObject(operation.getConfiguration(SOURCE_TAGS_PREFIX.concat(Integer.toString(number)).concat(MANDATORY_SUFFIX)));
        } else if (key.startsWith(SOURCE_FLAVOR_PREFIX) && !key.endsWith(MANDATORY_SUFFIX)) {
            number = NumberUtils.toInt(key.substring(SOURCE_FLAVOR_PREFIX.length()), -1);
            flavor = operation.getConfiguration(key);
            mandatory = BooleanUtils.toBooleanObject(operation.getConfiguration(SOURCE_FLAVOR_PREFIX.concat(Integer.toString(number)).concat(MANDATORY_SUFFIX)));
        }
        if (number < 0)
            continue;
        Tuple<TrackSelector, Boolean> selectorTuple = trackSelectors.get(number);
        if (selectorTuple == null) {
            selectorTuple = Tuple.tuple(new TrackSelector(), BooleanUtils.toBooleanDefaultIfNull(mandatory, false));
        } else {
            selectorTuple = Tuple.tuple(selectorTuple.getA(), selectorTuple.getB() || BooleanUtils.toBooleanDefaultIfNull(mandatory, false));
        }
        TrackSelector trackSelector = selectorTuple.getA();
        if (StringUtils.isNotBlank(tags)) {
            for (String tag : StringUtils.split(tags, ",")) {
                trackSelector.addTag(tag);
            }
        }
        if (StringUtils.isNotBlank(flavor)) {
            try {
                trackSelector.addFlavor(flavor);
            } catch (IllegalArgumentException e) {
                throw new WorkflowOperationException("Source flavor '" + flavor + "' is malformed");
            }
        }
        trackSelectors.put(number, selectorTuple);
    }
    return trackSelectors;
}
Also used : HashMap(java.util.HashMap) TrackSelector(org.opencastproject.mediapackage.selector.TrackSelector) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) Tuple(org.opencastproject.util.data.Tuple)

Example 27 with WorkflowOperationException

use of org.opencastproject.workflow.api.WorkflowOperationException in project opencast by opencast.

the class ConcatWorkflowOperationHandler method concat.

private WorkflowOperationResult concat(MediaPackage src, WorkflowOperationInstance operation) throws EncoderException, IOException, NotFoundException, MediaPackageException, WorkflowOperationException {
    MediaPackage mediaPackage = (MediaPackage) src.clone();
    Map<Integer, Tuple<TrackSelector, Boolean>> trackSelectors = getTrackSelectors(operation);
    String outputResolution = StringUtils.trimToNull(operation.getConfiguration(OUTPUT_RESOLUTION));
    String outputFrameRate = StringUtils.trimToNull(operation.getConfiguration(OUTPUT_FRAMERATE));
    String encodingProfile = StringUtils.trimToNull(operation.getConfiguration(ENCODING_PROFILE));
    // Skip the worklow if no source-flavors or tags has been configured
    if (trackSelectors.isEmpty()) {
        logger.warn("No source-tags or source-flavors has been set.");
        return createResult(mediaPackage, Action.SKIP);
    }
    String targetTagsOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_TAGS));
    String targetFlavorOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_FLAVOR));
    // Target tags
    List<String> targetTags = asList(targetTagsOption);
    // Target flavor
    if (targetFlavorOption == null)
        throw new WorkflowOperationException("Target flavor must be set!");
    // Find the encoding profile
    if (encodingProfile == null)
        throw new WorkflowOperationException("Encoding profile must be set!");
    EncodingProfile profile = composerService.getProfile(encodingProfile);
    if (profile == null)
        throw new WorkflowOperationException("Encoding profile '" + encodingProfile + "' was not found");
    // Output resolution
    if (outputResolution == null)
        throw new WorkflowOperationException("Output resolution must be set!");
    Dimension outputDimension = null;
    if (outputResolution.startsWith(OUTPUT_PART_PREFIX)) {
        if (!trackSelectors.keySet().contains(Integer.parseInt(outputResolution.substring(OUTPUT_PART_PREFIX.length()))))
            throw new WorkflowOperationException("Output resolution part not set!");
    } else {
        try {
            String[] outputResolutionArray = StringUtils.split(outputResolution, "x");
            if (outputResolutionArray.length != 2) {
                throw new WorkflowOperationException("Invalid format of output resolution!");
            }
            outputDimension = Dimension.dimension(Integer.parseInt(outputResolutionArray[0]), Integer.parseInt(outputResolutionArray[1]));
        } catch (WorkflowOperationException e) {
            throw e;
        } catch (Exception e) {
            throw new WorkflowOperationException("Unable to parse output resolution!", e);
        }
    }
    float fps = -1.0f;
    if (StringUtils.isNotEmpty(outputFrameRate)) {
        if (StringUtils.startsWith(outputFrameRate, OUTPUT_PART_PREFIX)) {
            if (!NumberUtils.isNumber(outputFrameRate.substring(OUTPUT_PART_PREFIX.length())) || !trackSelectors.keySet().contains(Integer.parseInt(outputFrameRate.substring(OUTPUT_PART_PREFIX.length())))) {
                throw new WorkflowOperationException("Output frame rate part not set or invalid!");
            }
        } else if (NumberUtils.isNumber(outputFrameRate)) {
            fps = NumberUtils.toFloat(outputFrameRate);
        } else {
            throw new WorkflowOperationException("Unable to parse output frame rate!");
        }
    }
    MediaPackageElementFlavor targetFlavor = null;
    try {
        targetFlavor = MediaPackageElementFlavor.parseFlavor(targetFlavorOption);
        if ("*".equals(targetFlavor.getType()) || "*".equals(targetFlavor.getSubtype()))
            throw new WorkflowOperationException("Target flavor must have a type and a subtype, '*' are not allowed!");
    } catch (IllegalArgumentException e) {
        throw new WorkflowOperationException("Target flavor '" + targetFlavorOption + "' is malformed");
    }
    List<Track> tracks = new ArrayList<Track>();
    for (Entry<Integer, Tuple<TrackSelector, Boolean>> trackSelector : trackSelectors.entrySet()) {
        Collection<Track> tracksForSelector = trackSelector.getValue().getA().select(mediaPackage, false);
        String currentFlavor = StringUtils.join(trackSelector.getValue().getA().getFlavors());
        String currentTag = StringUtils.join(trackSelector.getValue().getA().getTags());
        if (tracksForSelector.size() > 1) {
            logger.warn("More than one track has been found with flavor '{}' and/or tag '{}' for concat operation, skipping concatenation!", currentFlavor, currentTag);
            return createResult(mediaPackage, Action.SKIP);
        } else if (tracksForSelector.size() == 0 && trackSelector.getValue().getB()) {
            logger.warn("No track has been found with flavor '{}' and/or tag '{}' for concat operation, skipping concatenation!", currentFlavor, currentTag);
            return createResult(mediaPackage, Action.SKIP);
        } else if (tracksForSelector.size() == 0 && !trackSelector.getValue().getB()) {
            logger.info("No track has been found with flavor '{}' and/or tag '{}' for concat operation, skipping track!", currentFlavor, currentTag);
            continue;
        }
        for (Track t : tracksForSelector) {
            tracks.add(t);
            VideoStream[] videoStreams = TrackSupport.byType(t.getStreams(), VideoStream.class);
            if (videoStreams.length == 0) {
                logger.info("No video stream available in the track with flavor {}! {}", currentFlavor, t);
                return createResult(mediaPackage, Action.SKIP);
            }
            if (StringUtils.startsWith(outputResolution, OUTPUT_PART_PREFIX) && NumberUtils.isNumber(outputResolution.substring(OUTPUT_PART_PREFIX.length())) && trackSelector.getKey() == Integer.parseInt(outputResolution.substring(OUTPUT_PART_PREFIX.length()))) {
                outputDimension = new Dimension(videoStreams[0].getFrameWidth(), videoStreams[0].getFrameHeight());
                if (!trackSelector.getValue().getB()) {
                    logger.warn("Output resolution track {} must be mandatory, skipping concatenation!", outputResolution);
                    return createResult(mediaPackage, Action.SKIP);
                }
            }
            if (fps <= 0 && StringUtils.startsWith(outputFrameRate, OUTPUT_PART_PREFIX) && NumberUtils.isNumber(outputFrameRate.substring(OUTPUT_PART_PREFIX.length())) && trackSelector.getKey() == Integer.parseInt(outputFrameRate.substring(OUTPUT_PART_PREFIX.length()))) {
                fps = videoStreams[0].getFrameRate();
            }
        }
    }
    if (tracks.size() == 0) {
        logger.warn("No tracks found for concating operation, skipping concatenation!");
        return createResult(mediaPackage, Action.SKIP);
    } else if (tracks.size() == 1) {
        Track track = (Track) tracks.get(0).clone();
        track.setIdentifier(null);
        addNewTrack(mediaPackage, track, targetTags, targetFlavor);
        logger.info("At least two tracks are needed for the concating operation, skipping concatenation!");
        return createResult(mediaPackage, Action.SKIP);
    }
    Job concatJob;
    if (fps > 0) {
        concatJob = composerService.concat(profile.getIdentifier(), outputDimension, fps, tracks.toArray(new Track[tracks.size()]));
    } else {
        concatJob = composerService.concat(profile.getIdentifier(), outputDimension, tracks.toArray(new Track[tracks.size()]));
    }
    // Wait for the jobs to return
    if (!waitForStatus(concatJob).isSuccess())
        throw new WorkflowOperationException("The concat job did not complete successfully");
    if (concatJob.getPayload().length() > 0) {
        Track concatTrack = (Track) MediaPackageElementParser.getFromXml(concatJob.getPayload());
        concatTrack.setURI(workspace.moveTo(concatTrack.getURI(), mediaPackage.getIdentifier().toString(), concatTrack.getIdentifier(), "concat." + FilenameUtils.getExtension(concatTrack.getURI().toString())));
        addNewTrack(mediaPackage, concatTrack, targetTags, targetFlavor);
        WorkflowOperationResult result = createResult(mediaPackage, Action.CONTINUE, concatJob.getQueueTime());
        logger.debug("Concat operation completed");
        return result;
    } else {
        logger.info("concat operation unsuccessful, no payload returned: {}", concatJob);
        return createResult(mediaPackage, Action.SKIP);
    }
}
Also used : ArrayList(java.util.ArrayList) VideoStream(org.opencastproject.mediapackage.VideoStream) EncodingProfile(org.opencastproject.composer.api.EncodingProfile) Dimension(org.opencastproject.composer.layout.Dimension) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) NotFoundException(org.opencastproject.util.NotFoundException) IOException(java.io.IOException) MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) EncoderException(org.opencastproject.composer.api.EncoderException) WorkflowOperationResult(org.opencastproject.workflow.api.WorkflowOperationResult) MediaPackage(org.opencastproject.mediapackage.MediaPackage) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) Job(org.opencastproject.job.api.Job) Tuple(org.opencastproject.util.data.Tuple) Track(org.opencastproject.mediapackage.Track)

Example 28 with WorkflowOperationException

use of org.opencastproject.workflow.api.WorkflowOperationException in project opencast by opencast.

the class VideoSegmenterWorkflowOperationHandler method start.

/**
 * {@inheritDoc}
 *
 * @see org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance,
 *      JobContext)
 */
public WorkflowOperationResult start(final WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
    logger.debug("Running video segmentation on workflow {}", workflowInstance.getId());
    WorkflowOperationInstance operation = workflowInstance.getCurrentOperation();
    MediaPackage mediaPackage = workflowInstance.getMediaPackage();
    // Find movie track to analyze
    String trackFlavor = StringUtils.trimToNull(operation.getConfiguration(PROP_ANALYSIS_TRACK_FLAVOR));
    List<String> targetTags = asList(operation.getConfiguration(PROP_TARGET_TAGS));
    List<Track> candidates = new ArrayList<Track>();
    if (trackFlavor != null)
        candidates.addAll(Arrays.asList(mediaPackage.getTracks(MediaPackageElementFlavor.parseFlavor(trackFlavor))));
    else
        candidates.addAll(Arrays.asList(mediaPackage.getTracks(MediaPackageElements.PRESENTATION_SOURCE)));
    // Remove unsupported tracks (only those containing video can be segmented)
    Iterator<Track> ti = candidates.iterator();
    while (ti.hasNext()) {
        Track t = ti.next();
        if (!t.hasVideo())
            ti.remove();
    }
    // Found one?
    if (candidates.size() == 0) {
        logger.info("No matching tracks available for video segmentation in workflow {}", workflowInstance);
        return createResult(Action.CONTINUE);
    }
    // More than one left? Let's be pragmatic...
    if (candidates.size() > 1) {
        logger.info("Found more than one track to segment, choosing the first one ({})", candidates.get(0));
    }
    Track track = candidates.get(0);
    // Segment the media package
    Catalog mpeg7Catalog = null;
    Job job = null;
    try {
        job = videosegmenter.segment(track);
        if (!waitForStatus(job).isSuccess()) {
            throw new WorkflowOperationException("Video segmentation of " + track + " failed");
        }
        mpeg7Catalog = (Catalog) MediaPackageElementParser.getFromXml(job.getPayload());
        mediaPackage.add(mpeg7Catalog);
        mpeg7Catalog.setURI(workspace.moveTo(mpeg7Catalog.getURI(), mediaPackage.getIdentifier().toString(), mpeg7Catalog.getIdentifier(), "segments.xml"));
        mpeg7Catalog.setReference(new MediaPackageReferenceImpl(track));
        // Add target tags
        for (String tag : targetTags) {
            mpeg7Catalog.addTag(tag);
        }
    } catch (Exception e) {
        throw new WorkflowOperationException(e);
    }
    logger.debug("Video segmentation completed");
    return createResult(mediaPackage, Action.CONTINUE, job.getQueueTime());
}
Also used : ArrayList(java.util.ArrayList) Catalog(org.opencastproject.mediapackage.Catalog) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) WorkflowOperationInstance(org.opencastproject.workflow.api.WorkflowOperationInstance) MediaPackage(org.opencastproject.mediapackage.MediaPackage) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) MediaPackageReferenceImpl(org.opencastproject.mediapackage.MediaPackageReferenceImpl) Job(org.opencastproject.job.api.Job) Track(org.opencastproject.mediapackage.Track)

Example 29 with WorkflowOperationException

use of org.opencastproject.workflow.api.WorkflowOperationException in project opencast by opencast.

the class ConfigurablePublishWorkflowOperationHandler method start.

@Override
public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
    RequireUtil.notNull(workflowInstance, "workflowInstance");
    final MediaPackage mp = workflowInstance.getMediaPackage();
    final WorkflowOperationInstance op = workflowInstance.getCurrentOperation();
    final String channelId = StringUtils.trimToEmpty(op.getConfiguration(CHANNEL_ID_KEY));
    if ("".equals(channelId)) {
        throw new WorkflowOperationException("Unable to publish this mediapackage as the configuration key " + CHANNEL_ID_KEY + " is missing. Unable to determine where to publish these elements.");
    }
    final String urlPattern = StringUtils.trimToEmpty(op.getConfiguration(URL_PATTERN));
    MimeType mimetype = null;
    String mimetypeString = StringUtils.trimToEmpty(op.getConfiguration(MIME_TYPE));
    if (!"".equals(mimetypeString)) {
        try {
            mimetype = MimeTypes.parseMimeType(mimetypeString);
        } catch (IllegalArgumentException e) {
            throw new WorkflowOperationException("Unable to parse the provided configuration for " + MIME_TYPE, e);
        }
    }
    final boolean withPublishedElements = BooleanUtils.toBoolean(StringUtils.trimToEmpty(op.getConfiguration(WITH_PUBLISHED_ELEMENTS)));
    boolean checkAvailability = BooleanUtils.toBoolean(StringUtils.trimToEmpty(op.getConfiguration(CHECK_AVAILABILITY)));
    if (getPublications(mp, channelId).size() > 0) {
        final String rePublishStrategy = StringUtils.trimToEmpty(op.getConfiguration(STRATEGY));
        switch(rePublishStrategy) {
            case ("fail"):
                // fail is a dummy function for further distribution strategies
                fail(mp);
                break;
            case ("merge"):
                // nothing to do here. other publication strategies can be added to this list later on
                break;
            default:
                retract(mp, channelId);
        }
    }
    String mode = StringUtils.trimToEmpty(op.getConfiguration(MODE));
    if ("".equals(mode)) {
        mode = DEFAULT_MODE;
    } else if (!ArrayUtils.contains(KNOWN_MODES, mode)) {
        logger.error("Unknown value for configuration key mode: '{}'", mode);
        throw new IllegalArgumentException("Unknown value for configuration key mode");
    }
    final String[] sourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(SOURCE_FLAVORS)), ",");
    final String[] sourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(SOURCE_TAGS)), ",");
    String publicationUUID = UUID.randomUUID().toString();
    Publication publication = PublicationImpl.publication(publicationUUID, channelId, null, null);
    // Configure the element selector
    final SimpleElementSelector selector = new SimpleElementSelector();
    for (String flavor : sourceFlavors) {
        selector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor));
    }
    for (String tag : sourceTags) {
        selector.addTag(tag);
    }
    if (sourceFlavors.length > 0 || sourceTags.length > 0) {
        if (!withPublishedElements) {
            Set<MediaPackageElement> elements = distribute(selector.select(mp, false), mp, channelId, mode, checkAvailability);
            if (elements.size() > 0) {
                for (MediaPackageElement element : elements) {
                    // Make sure the mediapackage is prompted to create a new identifier for this element
                    element.setIdentifier(null);
                    PublicationImpl.addElementToPublication(publication, element);
                }
            } else {
                logger.info("No element found for distribution in media package '{}'", mp);
                return createResult(mp, Action.CONTINUE);
            }
        } else {
            List<MediaPackageElement> publishedElements = new ArrayList<>();
            for (Publication alreadyPublished : mp.getPublications()) {
                publishedElements.addAll(Arrays.asList(alreadyPublished.getAttachments()));
                publishedElements.addAll(Arrays.asList(alreadyPublished.getCatalogs()));
                publishedElements.addAll(Arrays.asList(alreadyPublished.getTracks()));
            }
            for (MediaPackageElement element : selector.select(publishedElements, false)) {
                PublicationImpl.addElementToPublication(publication, element);
            }
        }
    }
    if (!"".equals(urlPattern)) {
        publication.setURI(populateUrlWithVariables(urlPattern, mp, publicationUUID));
    }
    if (mimetype != null) {
        publication.setMimeType(mimetype);
    }
    mp.add(publication);
    return createResult(mp, Action.CONTINUE);
}
Also used : ArrayList(java.util.ArrayList) Publication(org.opencastproject.mediapackage.Publication) SimpleElementSelector(org.opencastproject.mediapackage.selector.SimpleElementSelector) MimeType(org.opencastproject.util.MimeType) WorkflowOperationInstance(org.opencastproject.workflow.api.WorkflowOperationInstance) MediaPackageElement(org.opencastproject.mediapackage.MediaPackageElement) MediaPackage(org.opencastproject.mediapackage.MediaPackage) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException)

Example 30 with WorkflowOperationException

use of org.opencastproject.workflow.api.WorkflowOperationException in project opencast by opencast.

the class ConfigurablePublishWorkflowOperationHandler method populateUrlWithVariables.

/**
 * Replace possible variables in the url-pattern configuration for this workflow operation handler.
 *
 * @param urlPattern
 *          The operation's template for replacing the variables.
 * @param mp
 *          The {@link MediaPackage} used to get the event / mediapackage id.
 * @param pubUUID
 *          The UUID for the published element.
 * @return The URI of the published element with the variables replaced.
 * @throws WorkflowOperationException
 *           Thrown if the URI is malformed after replacing the variables.
 */
public URI populateUrlWithVariables(String urlPattern, MediaPackage mp, String pubUUID) throws WorkflowOperationException {
    Map<String, Object> values = new HashMap<>();
    values.put(EVENT_ID_TEMPLATE_KEY, mp.getIdentifier().compact());
    values.put(PUBLICATION_ID_TEMPLATE_KEY, pubUUID);
    String playerPath = securityService.getOrganization().getProperties().get(PLAYER_PROPERTY);
    values.put(PLAYER_PATH_TEMPLATE_KEY, playerPath);
    values.put(SERIES_ID_TEMPLATE_KEY, StringUtils.trimToEmpty(mp.getSeries()));
    String uriWithVariables = DocUtil.processTextTemplate("Replacing Variables in Publish URL", urlPattern, values);
    URI publicationURI;
    try {
        publicationURI = new URI(uriWithVariables);
    } catch (URISyntaxException e) {
        throw new WorkflowOperationException(String.format("Unable to create URI from template '%s', replacement was: '%s'", urlPattern, uriWithVariables), e);
    }
    return publicationURI;
}
Also used : HashMap(java.util.HashMap) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI)

Aggregations

WorkflowOperationException (org.opencastproject.workflow.api.WorkflowOperationException)103 MediaPackage (org.opencastproject.mediapackage.MediaPackage)57 Job (org.opencastproject.job.api.Job)47 Track (org.opencastproject.mediapackage.Track)34 IOException (java.io.IOException)31 URI (java.net.URI)28 ArrayList (java.util.ArrayList)28 MediaPackageElementFlavor (org.opencastproject.mediapackage.MediaPackageElementFlavor)28 WorkflowOperationInstance (org.opencastproject.workflow.api.WorkflowOperationInstance)28 MediaPackageElement (org.opencastproject.mediapackage.MediaPackageElement)27 MediaPackageException (org.opencastproject.mediapackage.MediaPackageException)27 NotFoundException (org.opencastproject.util.NotFoundException)27 WorkflowOperationResult (org.opencastproject.workflow.api.WorkflowOperationResult)18 HashMap (java.util.HashMap)17 File (java.io.File)16 InputStream (java.io.InputStream)15 Attachment (org.opencastproject.mediapackage.Attachment)15 TrackSelector (org.opencastproject.mediapackage.selector.TrackSelector)15 ServiceRegistryException (org.opencastproject.serviceregistry.api.ServiceRegistryException)13 HashSet (java.util.HashSet)12