use of org.opencastproject.job.api.Job in project opencast by opencast.
the class SearchServiceRemoteImpl method add.
/**
* {@inheritDoc}
*
* @see org.opencastproject.search.api.SearchService#add(org.opencastproject.mediapackage.MediaPackage)
*/
@Override
public Job add(MediaPackage mediaPackage) throws SearchException {
HttpPost post = new HttpPost("/add");
try {
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
params.add(new BasicNameValuePair("mediapackage", MediaPackageParser.getAsXml(mediaPackage)));
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (Exception e) {
throw new SearchException("Unable to assemble a remote search request for mediapackage " + mediaPackage, e);
}
HttpResponse response = getResponse(post);
try {
if (response != null) {
Job job = JobParser.parseJob(response.getEntity().getContent());
logger.info("Publishing mediapackage '{}' using a remote search service", mediaPackage.getIdentifier());
return job;
}
} catch (Exception e) {
throw new SearchException("Unable to publish " + mediaPackage.getIdentifier() + " using a remote search service", e);
} finally {
closeConnection(response);
}
throw new SearchException("Unable to publish " + mediaPackage.getIdentifier() + " using a remote search service");
}
use of org.opencastproject.job.api.Job 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");
}
}
use of org.opencastproject.job.api.Job 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;
}
use of org.opencastproject.job.api.Job in project opencast by opencast.
the class PartialImportWorkflowOperationHandler method createVideoFromImage.
private Track createVideoFromImage(Attachment image, double time, List<MediaPackageElement> elementsToClean) throws EncoderException, MediaPackageException, WorkflowOperationException, NotFoundException {
Job imageToVideoJob = composerService.imageToVideo(image, IMAGE_MOVIE_PROFILE, time);
if (!waitForStatus(imageToVideoJob).isSuccess())
throw new WorkflowOperationException("Image to video job did not complete successfully");
// Get the latest copy
try {
imageToVideoJob = serviceRegistry.getJob(imageToVideoJob.getId());
} catch (ServiceRegistryException e) {
throw new WorkflowOperationException(e);
}
Track imageVideo = (Track) MediaPackageElementParser.getFromXml(imageToVideoJob.getPayload());
elementsToClean.add(imageVideo);
return imageVideo;
}
use of org.opencastproject.job.api.Job in project opencast by opencast.
the class PartialImportWorkflowOperationHandler method mux.
/**
* Mux a video and an audio track. Add the result to media package <code>mediaPackage</code> with the same flavor as
* the <code>video</code>.
*
* @return the mux job's queue time
*/
protected long mux(MediaPackage mediaPackage, Track video, Track audio, List<MediaPackageElement> elementsToClean) throws EncoderException, MediaPackageException, WorkflowOperationException, NotFoundException, ServiceRegistryException, IOException {
logger.debug("Muxing video {} and audio {}", video.getURI(), audio.getURI());
Job muxJob = composerService.mux(video, audio, PrepareAVWorkflowOperationHandler.MUX_AV_PROFILE);
if (!waitForStatus(muxJob).isSuccess()) {
throw new WorkflowOperationException("Muxing of audio " + audio + " and video " + video + " failed");
}
muxJob = serviceRegistry.getJob(muxJob.getId());
final Track muxed = (Track) MediaPackageElementParser.getFromXml(muxJob.getPayload());
if (muxed == null) {
throw new WorkflowOperationException("Muxed job " + muxJob + " returned no payload!");
}
muxed.setFlavor(video.getFlavor());
muxed.setURI(workspace.moveTo(muxed.getURI(), mediaPackage.getIdentifier().toString(), muxed.getIdentifier(), FilenameUtils.getName(video.getURI().toString())));
elementsToClean.add(audio);
mediaPackage.remove(audio);
elementsToClean.add(video);
mediaPackage.remove(video);
mediaPackage.add(muxed);
return muxJob.getQueueTime();
}
Aggregations