Search in sources :

Example 11 with MediaPackageElementFlavor

use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.

the class SearchRestService method getEpisode.

// CHECKSTYLE:OFF
@GET
@Path("episode.{format:xml|json}")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@RestQuery(name = "episodes", description = "Search for episodes matching the query parameters.", pathParameters = { @RestParameter(description = "The output format (json or xml) of the response body.", isRequired = true, name = "format", type = RestParameter.Type.STRING) }, restParameters = { @RestParameter(description = "The ID of the single episode to be returned, if it exists.", isRequired = false, name = "id", type = RestParameter.Type.STRING), @RestParameter(description = "Any episode that matches this free-text query.", isRequired = false, name = "q", type = RestParameter.Type.STRING), @RestParameter(description = "Any episode that belongs to specified series id.", isRequired = false, name = "sid", type = RestParameter.Type.STRING), // isRequired = false, name = "episodes", type = RestParameter.Type.STRING),
@RestParameter(name = "sort", isRequired = false, description = "The sort order.  May include any " + "of the following: DATE_CREATED, DATE_PUBLISHED, TITLE, SERIES_ID, MEDIA_PACKAGE_ID, CREATOR, " + "CONTRIBUTOR, LANGUAGE, LICENSE, SUBJECT, DESCRIPTION, PUBLISHER.  Add '_DESC' to reverse the sort order (e.g. TITLE_DESC).", type = RestParameter.Type.STRING), @RestParameter(defaultValue = "20", description = "The maximum number of items to return per page.", isRequired = false, name = "limit", type = RestParameter.Type.STRING), @RestParameter(defaultValue = "0", description = "The page number.", isRequired = false, name = "offset", type = RestParameter.Type.STRING), @RestParameter(defaultValue = "false", description = "Whether this is an administrative query", isRequired = false, name = "admin", type = RestParameter.Type.BOOLEAN) }, reponses = { @RestResponse(description = "The request was processed succesfully.", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "The search results, expressed as xml or json.")
public Response getEpisode(@QueryParam("id") String id, @QueryParam("q") String text, @QueryParam("sid") String seriesId, @QueryParam("sort") String sort, @QueryParam("tag") String[] tags, @QueryParam("flavor") String[] flavors, @QueryParam("limit") int limit, @QueryParam("offset") int offset, @QueryParam("admin") boolean admin, @PathParam("format") String format) throws SearchException, UnauthorizedException {
    // CHECKSTYLE:ON
    // Prepare the flavors
    List<MediaPackageElementFlavor> flavorSet = new ArrayList<MediaPackageElementFlavor>();
    if (flavors != null) {
        for (String f : flavors) {
            try {
                flavorSet.add(MediaPackageElementFlavor.parseFlavor(f));
            } catch (IllegalArgumentException e) {
                logger.debug("invalid flavor '{}' specified in query", f);
            }
        }
    }
    SearchQuery search = new SearchQuery();
    search.withId(id).withSeriesId(seriesId).withElementFlavors(flavorSet.toArray(new MediaPackageElementFlavor[flavorSet.size()])).withElementTags(tags).withLimit(limit).withOffset(offset);
    if (StringUtils.isNotBlank(text)) {
        search.withText(text);
    }
    search.withSort(SearchQuery.Sort.DATE_CREATED, false);
    if (StringUtils.isNotBlank(sort)) {
        // Parse the sort field and direction
        SearchQuery.Sort sortField = null;
        if (sort.endsWith(DESCENDING_SUFFIX)) {
            String enumKey = sort.substring(0, sort.length() - DESCENDING_SUFFIX.length()).toUpperCase();
            try {
                sortField = SearchQuery.Sort.valueOf(enumKey);
                search.withSort(sortField, false);
            } catch (IllegalArgumentException e) {
                logger.warn("No sort enum matches '{}'", enumKey);
            }
        } else {
            try {
                sortField = SearchQuery.Sort.valueOf(sort);
                search.withSort(sortField);
            } catch (IllegalArgumentException e) {
                logger.warn("No sort enum matches '{}'", sort);
            }
        }
    }
    // Build the response
    ResponseBuilder rb = Response.ok();
    if (admin) {
        rb.entity(searchService.getForAdministrativeRead(search));
    } else {
        rb.entity(searchService.getByQuery(search));
    }
    if ("json".equals(format)) {
        rb.type(MediaType.APPLICATION_JSON);
    } else {
        rb.type(MediaType.TEXT_XML);
    }
    return rb.build();
}
Also used : SearchQuery(org.opencastproject.search.api.SearchQuery) ArrayList(java.util.ArrayList) ResponseBuilder(javax.ws.rs.core.Response.ResponseBuilder) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) RestQuery(org.opencastproject.util.doc.rest.RestQuery)

Example 12 with MediaPackageElementFlavor

use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.

the class ImageToVideoWorkflowOperationHandler method imageToVideo.

private WorkflowOperationResult imageToVideo(MediaPackage mp, WorkflowInstance wi) throws Exception {
    // read cfg
    final List<String> sourceTags = getCfg(wi, OPT_SOURCE_TAGS).map(asList).getOrElse(nil(String.class));
    final Option<MediaPackageElementFlavor> sourceFlavor = getCfg(wi, OPT_SOURCE_FLAVOR).map(MediaPackageElementFlavor.parseFlavor);
    if (sourceFlavor.isNone() && sourceTags.isEmpty()) {
        logger.warn("No source tags or flavor are given to determine the image to use");
        return createResult(mp, Action.SKIP);
    }
    final List<String> targetTags = getCfg(wi, OPT_TARGET_TAGS).map(asList).getOrElse(nil(String.class));
    final Option<MediaPackageElementFlavor> targetFlavor = getCfg(wi, OPT_TARGET_FLAVOR).map(MediaPackageElementFlavor.parseFlavor);
    final double duration = getCfg(wi, OPT_DURATION).bind(Strings.toDouble).getOrElse(this.<Double>cfgKeyMissing(OPT_DURATION));
    final String profile = getCfg(wi, OPT_PROFILE).getOrElse(this.<String>cfgKeyMissing(OPT_PROFILE));
    // run image to video jobs
    final List<Job> jobs = Monadics.<MediaPackageElement>mlist(mp.getAttachments()).filter(sourceFlavor.map(Filters.matchesFlavor).getOrElse(Booleans.<MediaPackageElement>yes())).filter(Filters.hasTagAny(sourceTags)).map(Misc.<MediaPackageElement, Attachment>cast()).map(imageToVideo(profile, duration)).value();
    if (JobUtil.waitForJobs(serviceRegistry, jobs).isSuccess()) {
        for (final Job job : jobs) {
            if (job.getPayload().length() > 0) {
                Track track = (Track) MediaPackageElementParser.getFromXml(job.getPayload());
                track.setURI(workspace.moveTo(track.getURI(), mp.getIdentifier().toString(), track.getIdentifier(), FilenameUtils.getName(track.getURI().toString())));
                // Adjust the target tags
                for (String tag : targetTags) {
                    track.addTag(tag);
                }
                // Adjust the target flavor.
                for (MediaPackageElementFlavor flavor : targetFlavor) {
                    track.setFlavor(flavor);
                }
                // store new tracks to mediaPackage
                mp.add(track);
                logger.debug("Image to video operation completed");
            } else {
                logger.info("Image to video operation unsuccessful, no payload returned: {}", job);
                return createResult(mp, Action.SKIP);
            }
        }
        return createResult(mp, Action.CONTINUE, mlist(jobs).foldl(0L, new Function2<Long, Job, Long>() {

            @Override
            public Long apply(Long max, Job job) {
                return Math.max(max, job.getQueueTime());
            }
        }));
    } else {
        throw new WorkflowOperationException("The image to video encoding jobs did not return successfully");
    }
}
Also used : MediaPackageElement(org.opencastproject.mediapackage.MediaPackageElement) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) Function2(org.opencastproject.util.data.Function2) Job(org.opencastproject.job.api.Job) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) Track(org.opencastproject.mediapackage.Track)

Example 13 with MediaPackageElementFlavor

use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.

the class EncodeWorkflowOperationHandler method encode.

/**
 * Encode tracks from MediaPackage using profiles stored in properties and updates current MediaPackage.
 *
 * @param src
 *          The source media package
 * @param operation
 *          the current workflow operation
 * @return the operation result containing the updated media package
 * @throws EncoderException
 *           if encoding fails
 * @throws WorkflowOperationException
 *           if errors occur during processing
 * @throws IOException
 *           if the workspace operations fail
 * @throws NotFoundException
 *           if the workspace doesn't contain the requested file
 */
private WorkflowOperationResult encode(MediaPackage src, WorkflowOperationInstance operation) throws EncoderException, IOException, NotFoundException, MediaPackageException, WorkflowOperationException {
    MediaPackage mediaPackage = (MediaPackage) src.clone();
    // Check which tags have been configured
    String sourceTagsOption = StringUtils.trimToNull(operation.getConfiguration("source-tags"));
    String targetTagsOption = StringUtils.trimToNull(operation.getConfiguration("target-tags"));
    String sourceFlavorOption = StringUtils.trimToNull(operation.getConfiguration("source-flavor"));
    String sourceFlavorsOption = StringUtils.trimToNull(operation.getConfiguration("source-flavors"));
    String targetFlavorOption = StringUtils.trimToNull(operation.getConfiguration("target-flavor"));
    AbstractMediaPackageElementSelector<Track> elementSelector = new TrackSelector();
    // Make sure either one of tags or flavors are provided
    if (StringUtils.isBlank(sourceTagsOption) && StringUtils.isBlank(sourceFlavorOption) && StringUtils.isBlank(sourceFlavorsOption)) {
        logger.info("No source tags or flavors have been specified, not matching anything");
        return createResult(mediaPackage, Action.CONTINUE);
    }
    // Select the source flavors
    for (String flavor : asList(sourceFlavorsOption)) {
        try {
            elementSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor));
        } catch (IllegalArgumentException e) {
            throw new WorkflowOperationException("Source flavor '" + flavor + "' is malformed");
        }
    }
    // Support legacy "source-flavor" option
    if (StringUtils.isNotBlank(sourceFlavorOption)) {
        String flavor = StringUtils.trim(sourceFlavorOption);
        try {
            elementSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor));
        } catch (IllegalArgumentException e) {
            throw new WorkflowOperationException("Source flavor '" + flavor + "' is malformed");
        }
    }
    // Select the source tags
    for (String tag : asList(sourceTagsOption)) {
        elementSelector.addTag(tag);
    }
    // Find the encoding profile
    String profilesOption = StringUtils.trimToNull(operation.getConfiguration("encoding-profiles"));
    List<EncodingProfile> profiles = new ArrayList<EncodingProfile>();
    for (String profileName : asList(profilesOption)) {
        EncodingProfile profile = composerService.getProfile(profileName);
        if (profile == null)
            throw new WorkflowOperationException("Encoding profile '" + profileName + "' was not found");
        profiles.add(profile);
    }
    // Support legacy "encoding-profile" option
    String profileOption = StringUtils.trimToNull(operation.getConfiguration("encoding-profile"));
    if (StringUtils.isNotBlank(profileOption)) {
        String profileId = StringUtils.trim(profileOption);
        EncodingProfile profile = composerService.getProfile(profileId);
        if (profile == null)
            throw new WorkflowOperationException("Encoding profile '" + profileId + "' was not found");
        profiles.add(profile);
    }
    // Make sure there is at least one profile
    if (profiles.isEmpty())
        throw new WorkflowOperationException("No encoding profile was specified");
    // Target tags
    List<String> targetTags = asList(targetTagsOption);
    // Target flavor
    MediaPackageElementFlavor targetFlavor = null;
    if (StringUtils.isNotBlank(targetFlavorOption)) {
        try {
            targetFlavor = MediaPackageElementFlavor.parseFlavor(targetFlavorOption);
        } catch (IllegalArgumentException e) {
            throw new WorkflowOperationException("Target flavor '" + targetFlavorOption + "' is malformed");
        }
    }
    // Look for elements matching the tag
    Collection<Track> elements = elementSelector.select(mediaPackage, false);
    // Encode all tracks found
    long totalTimeInQueue = 0;
    Map<Job, JobInformation> encodingJobs = new HashMap<Job, JobInformation>();
    for (Track track : elements) {
        // Encode the track with all profiles
        for (EncodingProfile profile : profiles) {
            // Check if the track supports the output type of the profile
            MediaType outputType = profile.getOutputType();
            if (outputType.equals(MediaType.Audio) && !track.hasAudio()) {
                logger.info("Skipping encoding of '{}', since it lacks an audio stream", track);
                continue;
            } else if (outputType.equals(MediaType.Visual) && !track.hasVideo()) {
                logger.info("Skipping encoding of '{}', since it lacks a video stream", track);
                continue;
            }
            logger.info("Encoding track {} using encoding profile '{}'", track, profile);
            // Start encoding and wait for the result
            encodingJobs.put(composerService.parallelEncode(track, profile.getIdentifier()), new JobInformation(track, profile));
        }
    }
    if (encodingJobs.isEmpty()) {
        logger.info("No matching tracks found");
        return createResult(mediaPackage, Action.CONTINUE);
    }
    // Wait for the jobs to return
    if (!waitForStatus(encodingJobs.keySet().toArray(new Job[encodingJobs.size()])).isSuccess()) {
        throw new WorkflowOperationException("One of the encoding jobs did not complete successfully");
    }
    // Process the result
    for (Map.Entry<Job, JobInformation> entry : encodingJobs.entrySet()) {
        Job job = entry.getKey();
        Track track = entry.getValue().getTrack();
        // add this receipt's queue time to the total
        totalTimeInQueue += job.getQueueTime();
        // it is allowed for compose jobs to return an empty payload. See the EncodeEngine interface
        if (job.getPayload().length() > 0) {
            List<Track> composedTracks = (List<Track>) MediaPackageElementParser.getArrayFromXml(job.getPayload());
            // Adjust the target tags
            for (Track encodedTrack : composedTracks) {
                for (String tag : targetTags) {
                    logger.trace("Tagging composed track {} with '{}'", encodedTrack.toString(), tag);
                    encodedTrack.addTag(tag);
                }
            }
            // Adjust the target flavor. Make sure to account for partial updates
            if (targetFlavor != null) {
                String flavorType = targetFlavor.getType();
                String flavorSubtype = targetFlavor.getSubtype();
                if ("*".equals(flavorType))
                    flavorType = track.getFlavor().getType();
                if ("*".equals(flavorSubtype))
                    flavorSubtype = track.getFlavor().getSubtype();
                for (Track encodedTrack : composedTracks) {
                    encodedTrack.setFlavor(new MediaPackageElementFlavor(flavorType, flavorSubtype));
                    logger.debug("Composed track {} has flavor '{}'", encodedTrack.toString(), encodedTrack.getFlavor());
                }
            }
            // store new tracks to mediaPackage
            for (Track encodedTrack : composedTracks) {
                mediaPackage.addDerived(encodedTrack, track);
                String fileName = getFileNameFromElements(track, encodedTrack);
                encodedTrack.setURI(workspace.moveTo(encodedTrack.getURI(), mediaPackage.getIdentifier().toString(), encodedTrack.getIdentifier(), fileName));
            }
        }
    }
    WorkflowOperationResult result = createResult(mediaPackage, Action.CONTINUE, totalTimeInQueue);
    logger.debug("Parallel encode operation completed");
    return result;
}
Also used : HashMap(java.util.HashMap) TrackSelector(org.opencastproject.mediapackage.selector.TrackSelector) ArrayList(java.util.ArrayList) EncodingProfile(org.opencastproject.composer.api.EncodingProfile) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) WorkflowOperationResult(org.opencastproject.workflow.api.WorkflowOperationResult) MediaPackage(org.opencastproject.mediapackage.MediaPackage) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) MediaType(org.opencastproject.composer.api.EncodingProfile.MediaType) ArrayList(java.util.ArrayList) List(java.util.List) Job(org.opencastproject.job.api.Job) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) Track(org.opencastproject.mediapackage.Track)

Example 14 with MediaPackageElementFlavor

use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.

the class ImageWorkflowOperationHandler method configure.

/**
 * Get and parse the configuration options.
 */
private Cfg configure(MediaPackage mp, WorkflowOperationInstance woi) throws WorkflowOperationException {
    final List<EncodingProfile> profiles = getOptConfig(woi, OPT_PROFILES).toStream().bind(asList.toFn()).map(fetchProfile(composerService)).toList();
    final List<String> targetImageTags = getOptConfig(woi, OPT_TARGET_TAGS).toStream().bind(asList.toFn()).toList();
    final Opt<MediaPackageElementFlavor> targetImageFlavor = getOptConfig(woi, OPT_TARGET_FLAVOR).map(MediaPackageElementFlavor.parseFlavor.toFn());
    final List<Track> sourceTracks;
    {
        // get the source flavors
        final Stream<MediaPackageElementFlavor> sourceFlavors = getOptConfig(woi, OPT_SOURCE_FLAVORS).toStream().bind(Strings.splitCsv).append(getOptConfig(woi, OPT_SOURCE_FLAVOR)).map(MediaPackageElementFlavor.parseFlavor.toFn());
        // get the source tags
        final Stream<String> sourceTags = getOptConfig(woi, OPT_SOURCE_TAGS).toStream().bind(Strings.splitCsv);
        // fold both into a selector
        final TrackSelector trackSelector = sourceTags.apply(tagFold(sourceFlavors.apply(flavorFold(new TrackSelector()))));
        // select the tracks based on source flavors and tags and skip those that don't have video
        sourceTracks = $(trackSelector.select(mp, true)).filter(Filters.hasVideo.toFn()).each(new Fx<Track>() {

            @Override
            public void apply(Track track) {
                if (track.getDuration() == null) {
                    chuck(new WorkflowOperationException(format("Track %s cannot tell its duration", track)));
                }
            }
        }).toList();
    }
    final List<MediaPosition> positions = parsePositions(getConfig(woi, OPT_POSITIONS));
    final long endMargin = getOptConfig(woi, OPT_END_MARGIN).bind(Strings.toLong).getOr(END_MARGIN_DEFAULT);
    // 
    return new Cfg(sourceTracks, positions, profiles, targetImageFlavor, targetImageTags, getTargetBaseNameFormat(woi, OPT_TARGET_BASE_NAME_FORMAT_SECOND), getTargetBaseNameFormat(woi, OPT_TARGET_BASE_NAME_FORMAT_PERCENT), endMargin);
}
Also used : TrackSelector(org.opencastproject.mediapackage.selector.TrackSelector) EncodingProfile(org.opencastproject.composer.api.EncodingProfile) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) Fx(com.entwinemedia.fn.Fx) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) Stream(com.entwinemedia.fn.Stream) Track(org.opencastproject.mediapackage.Track)

Example 15 with MediaPackageElementFlavor

use of org.opencastproject.mediapackage.MediaPackageElementFlavor in project opencast by opencast.

the class PartialImportWorkflowOperationHandler method createCopyOfTrack.

/**
 * This function creates a copy of a given track in the media package
 *
 * @param mediaPackage
 *          The media package being processed.
 * @param track
 *          The track we want to create a copy from.
 * @param targetFlavor
 *          The target flavor for the copy of the track.
 */
private void createCopyOfTrack(MediaPackage mediaPackage, Track track, MediaPackageElementFlavor targetFlavor) throws IllegalArgumentException, NotFoundException, IOException {
    MediaPackageElementFlavor targetCopyFlavor = null;
    if (track.hasVideo()) {
        targetCopyFlavor = targetFlavor;
    } else {
        targetCopyFlavor = deriveAudioFlavor(targetFlavor);
    }
    logger.debug("Copying track {} with flavor {} using target flavor {}", track.getURI(), track.getFlavor(), targetCopyFlavor);
    copyPartialToSource(mediaPackage, targetCopyFlavor, track);
}
Also used : MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor)

Aggregations

MediaPackageElementFlavor (org.opencastproject.mediapackage.MediaPackageElementFlavor)109 MediaPackage (org.opencastproject.mediapackage.MediaPackage)49 Track (org.opencastproject.mediapackage.Track)34 URI (java.net.URI)31 Test (org.junit.Test)31 WorkflowOperationException (org.opencastproject.workflow.api.WorkflowOperationException)28 IOException (java.io.IOException)27 NotFoundException (org.opencastproject.util.NotFoundException)27 ArrayList (java.util.ArrayList)26 WorkflowOperationResult (org.opencastproject.workflow.api.WorkflowOperationResult)26 HashMap (java.util.HashMap)23 MediaPackageElement (org.opencastproject.mediapackage.MediaPackageElement)22 MediaPackageException (org.opencastproject.mediapackage.MediaPackageException)22 Job (org.opencastproject.job.api.Job)21 WorkflowOperationInstance (org.opencastproject.workflow.api.WorkflowOperationInstance)19 InputStream (java.io.InputStream)18 TrackImpl (org.opencastproject.mediapackage.track.TrackImpl)17 TrackSelector (org.opencastproject.mediapackage.selector.TrackSelector)16 File (java.io.File)13 Catalog (org.opencastproject.mediapackage.Catalog)13