use of org.opencastproject.mediapackage.Attachment in project opencast by opencast.
the class ComposerServiceImpl method extractImages.
private List<Attachment> extractImages(Job job, Track sourceTrack, String profileId, Map<String, String> properties, double... times) throws EncoderException {
logger.info("creating an image using video track {}", sourceTrack.getIdentifier());
// Get the encoding profile
final EncodingProfile profile = getProfile(job, profileId);
// Create the encoding engine
final EncoderEngine encoderEngine = getEncoderEngine();
// Finally get the file that needs to be encoded
File videoFile = loadTrackIntoWorkspace(job, "video", sourceTrack);
// Do the work
List<File> encodingOutput;
try {
encodingOutput = encoderEngine.extract(videoFile, profile, properties, times);
// check for validity of output
if (encodingOutput == null || encodingOutput.isEmpty()) {
logger.error("Image extraction from video {} with profile {} failed: no images were produced", sourceTrack.getURI(), profile.getIdentifier());
throw new EncoderException("Image extraction failed: no images were produced");
}
} catch (EncoderException e) {
Map<String, String> params = new HashMap<>();
params.put("video", sourceTrack.getURI().toString());
params.put("profile", profile.getIdentifier());
params.put("positions", Arrays.toString(times));
incident().recordFailure(job, IMAGE_EXTRACTION_FAILED, e, params, detailsFor(e, encoderEngine));
throw e;
} finally {
activeEncoder.remove(encoderEngine);
}
int i = 0;
List<URI> workspaceURIs = new LinkedList<>();
for (File output : encodingOutput) {
if (!output.exists() || output.length() == 0) {
logger.warn("Extracted image {} is empty!", output);
throw new EncoderException("Extracted image " + output.toString() + " is empty!");
}
// Put the file in the workspace
InputStream in = null;
try {
in = new FileInputStream(output);
URI returnURL = workspace.putInCollection(COLLECTION, job.getId() + "_" + i++ + "." + FilenameUtils.getExtension(output.getAbsolutePath()), in);
logger.debug("Copied image file to the workspace at {}", returnURL);
workspaceURIs.add(returnURL);
} catch (Exception e) {
cleanup(encodingOutput.toArray(new File[encodingOutput.size()]));
cleanupWorkspace(workspaceURIs.toArray(new URI[workspaceURIs.size()]));
incident().recordFailure(job, WORKSPACE_PUT_COLLECTION_IO_EXCEPTION, e, getWorkspaceCollectionParams("extracted image file", COLLECTION, output.toURI()), NO_DETAILS);
throw new EncoderException("Unable to put image file into the workspace", e);
} finally {
IOUtils.closeQuietly(in);
}
}
// cleanup
cleanup(encodingOutput.toArray(new File[encodingOutput.size()]));
MediaPackageElementBuilder builder = MediaPackageElementBuilderFactory.newInstance().newElementBuilder();
List<Attachment> imageAttachments = new LinkedList<Attachment>();
for (URI url : workspaceURIs) {
Attachment attachment = (Attachment) builder.elementFromURI(url, Attachment.TYPE, null);
imageAttachments.add(attachment);
}
return imageAttachments;
}
use of org.opencastproject.mediapackage.Attachment in project opencast by opencast.
the class ComposerServiceImpl method process.
/**
* {@inheritDoc}
*
* @see org.opencastproject.job.api.AbstractJobProducer#process(org.opencastproject.job.api.Job)
*/
@Override
protected String process(Job job) throws ServiceRegistryException {
String operation = job.getOperation();
List<String> arguments = job.getArguments();
try {
Operation op = Operation.valueOf(operation);
Track firstTrack;
Track secondTrack;
String encodingProfile = arguments.get(0);
final String serialized;
switch(op) {
case Encode:
firstTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(1));
serialized = encode(job, Collections.map(tuple("video", firstTrack)), encodingProfile).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
case ParallelEncode:
firstTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(1));
serialized = MediaPackageElementParser.getArrayAsXml(parallelEncode(job, firstTrack, encodingProfile));
break;
case Image:
firstTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(1));
List<Attachment> resultingElements;
if (Boolean.parseBoolean(arguments.get(2))) {
double[] times = new double[arguments.size() - 3];
for (int i = 3; i < arguments.size(); i++) {
times[i - 3] = Double.parseDouble(arguments.get(i));
}
resultingElements = image(job, firstTrack, encodingProfile, times);
} else {
Map<String, String> properties = parseProperties(arguments.get(3));
resultingElements = image(job, firstTrack, encodingProfile, properties);
}
serialized = MediaPackageElementParser.getArrayAsXml(resultingElements);
break;
case ImageConversion:
Attachment sourceImage = (Attachment) MediaPackageElementParser.getFromXml(arguments.get(1));
serialized = convertImage(job, sourceImage, encodingProfile).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
case Mux:
firstTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(1));
secondTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(2));
serialized = mux(job, firstTrack, secondTrack, encodingProfile).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
case Trim:
firstTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(1));
long start = Long.parseLong(arguments.get(2));
long duration = Long.parseLong(arguments.get(3));
serialized = trim(job, firstTrack, encodingProfile, start, duration).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
case Composite:
Attachment watermarkAttachment;
firstTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(LOWER_TRACK_INDEX));
Layout lowerLayout = Serializer.layout(JsonObj.jsonObj(arguments.get(LOWER_TRACK_LAYOUT_INDEX)));
LaidOutElement<Track> lowerLaidOutElement = new LaidOutElement<>(firstTrack, lowerLayout);
Option<LaidOutElement<Track>> upperLaidOutElement = Option.none();
if (NOT_AVAILABLE.equals(arguments.get(UPPER_TRACK_INDEX)) && NOT_AVAILABLE.equals(arguments.get(UPPER_TRACK_LAYOUT_INDEX))) {
logger.trace("This composite action does not use a second track.");
} else {
secondTrack = (Track) MediaPackageElementParser.getFromXml(arguments.get(UPPER_TRACK_INDEX));
Layout upperLayout = Serializer.layout(JsonObj.jsonObj(arguments.get(UPPER_TRACK_LAYOUT_INDEX)));
upperLaidOutElement = Option.option(new LaidOutElement<Track>(secondTrack, upperLayout));
}
Dimension compositeTrackSize = Serializer.dimension(JsonObj.jsonObj(arguments.get(COMPOSITE_TRACK_SIZE_INDEX)));
String backgroundColor = arguments.get(BACKGROUND_COLOR_INDEX);
Option<LaidOutElement<Attachment>> watermarkOption = Option.none();
if (arguments.size() == 9) {
watermarkAttachment = (Attachment) MediaPackageElementParser.getFromXml(arguments.get(WATERMARK_INDEX));
Layout watermarkLayout = Serializer.layout(JsonObj.jsonObj(arguments.get(WATERMARK_LAYOUT_INDEX)));
watermarkOption = Option.some(new LaidOutElement<>(watermarkAttachment, watermarkLayout));
}
serialized = composite(job, compositeTrackSize, lowerLaidOutElement, upperLaidOutElement, watermarkOption, encodingProfile, backgroundColor).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
case Concat:
String dimensionString = arguments.get(1);
String frameRateString = arguments.get(2);
Dimension outputDimension = null;
if (StringUtils.isNotBlank(dimensionString))
outputDimension = Serializer.dimension(JsonObj.jsonObj(dimensionString));
float outputFrameRate = NumberUtils.toFloat(frameRateString, -1.0f);
List<Track> tracks = new ArrayList<>();
for (int i = 3; i < arguments.size(); i++) {
tracks.add(i - 3, (Track) MediaPackageElementParser.getFromXml(arguments.get(i)));
}
serialized = concat(job, tracks, encodingProfile, outputDimension, outputFrameRate).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
case ImageToVideo:
Attachment image = (Attachment) MediaPackageElementParser.getFromXml(arguments.get(1));
double time = Double.parseDouble(arguments.get(2));
serialized = imageToVideo(job, image, encodingProfile, time).map(MediaPackageElementParser.getAsXml()).getOrElse("");
break;
default:
throw new IllegalStateException("Don't know how to handle operation '" + operation + "'");
}
return serialized;
} catch (IllegalArgumentException e) {
throw new ServiceRegistryException(String.format("Cannot handle operations of type '%s'", operation), e);
} catch (IndexOutOfBoundsException e) {
throw new ServiceRegistryException(String.format("Invalid arguments for operation '%s'", operation), e);
} catch (Exception e) {
throw new ServiceRegistryException(String.format("Error handling operation '%s'", operation), e);
}
}
use of org.opencastproject.mediapackage.Attachment in project opencast by opencast.
the class ComposerServiceTest method testImageToVideo.
/**
* Test method for
* {@link org.opencastproject.composer.impl.ComposerServiceImpl#imageToVideo(org.opencastproject.mediapackage.Attachment, String, Long)}
*/
@Test
public void testImageToVideo() throws Exception {
if (!ffmpegInstalled)
return;
assertTrue(sourceImage.isFile());
// Need different media files
Workspace workspace = EasyMock.createNiceMock(Workspace.class);
EasyMock.expect(workspace.get(EasyMock.anyObject())).andReturn(sourceImage).anyTimes();
EasyMock.expect(workspace.putInCollection(EasyMock.anyString(), EasyMock.anyString(), EasyMock.anyObject())).andReturn(sourceImage.toURI()).anyTimes();
composerService.setWorkspace(workspace);
EasyMock.replay(workspace);
EncodingProfile imageToVideoProfile = profileScanner.getProfile("image-movie.work");
Attachment attachment = AttachmentImpl.fromURI(sourceImage.toURI());
attachment.setIdentifier("test image");
Job imageToVideo = composerService.imageToVideo(attachment, imageToVideoProfile.getIdentifier(), 1L);
Track imageToVideoTrack = (Track) MediaPackageElementParser.getFromXml(imageToVideo.getPayload());
Assert.assertNotNull(imageToVideoTrack);
inspectedTrack.setIdentifier(imageToVideoTrack.getIdentifier());
inspectedTrack.setMimeType(MimeType.mimeType("video", "mp4"));
Assert.assertEquals(inspectedTrack, imageToVideoTrack);
}
use of org.opencastproject.mediapackage.Attachment in project opencast by opencast.
the class PartialImportWorkflowOperationHandler method getSilentAudio.
private Track getSilentAudio(final double time, final List<MediaPackageElement> elementsToClean, final Long operationId) throws EncoderException, MediaPackageException, WorkflowOperationException, NotFoundException, IOException {
final URI uri = workspace.putInCollection(COLLECTION_ID, operationId + "-silent", new ByteArrayInputStream(EMPTY_VALUE.getBytes()));
final Attachment emptyAttachment = (Attachment) MediaPackageElementBuilderFactory.newInstance().newElementBuilder().elementFromURI(uri, Type.Attachment, MediaPackageElementFlavor.parseFlavor("audio/silent"));
elementsToClean.add(emptyAttachment);
final Job silentAudioJob = composerService.imageToVideo(emptyAttachment, SILENT_AUDIO_PROFILE, time);
if (!waitForStatus(silentAudioJob).isSuccess())
throw new WorkflowOperationException("Silent audio job did not complete successfully");
// Get the latest copy
try {
for (final String payload : getPayload(serviceRegistry, silentAudioJob)) {
final Track silentAudio = (Track) MediaPackageElementParser.getFromXml(payload);
elementsToClean.add(silentAudio);
return silentAudio;
}
// none
throw new WorkflowOperationException(format("Job %s has no payload or cannot be updated", silentAudioJob));
} catch (ServiceRegistryException ex) {
throw new WorkflowOperationException(ex);
}
}
use of org.opencastproject.mediapackage.Attachment in project opencast by opencast.
the class PartialImportWorkflowOperationHandler method extractLastImageFrame.
private Attachment extractLastImageFrame(Track presentationTrack, List<MediaPackageElement> elementsToClean) throws EncoderException, MediaPackageException, WorkflowOperationException, NotFoundException {
VideoStream[] videoStreams = TrackSupport.byType(presentationTrack.getStreams(), VideoStream.class);
Map<String, String> properties = new HashMap<String, String>();
properties.put("frame", Long.toString(videoStreams[0].getFrameCount() - 1));
Job extractImageJob = composerService.image(presentationTrack, IMAGE_FRAME_PROFILE, properties);
if (!waitForStatus(extractImageJob).isSuccess())
throw new WorkflowOperationException("Extract image frame video job did not complete successfully");
// Get the latest copy
try {
extractImageJob = serviceRegistry.getJob(extractImageJob.getId());
} catch (ServiceRegistryException e) {
throw new WorkflowOperationException(e);
}
Attachment composedImages = (Attachment) MediaPackageElementParser.getArrayFromXml(extractImageJob.getPayload()).get(0);
elementsToClean.add(composedImages);
return composedImages;
}
Aggregations