use of org.opencastproject.smil.api.SmilException in project opencast by opencast.
the class ToolsEndpoint method getSegments.
/**
* Analyzes the media package and tries to get information about segments out of it.
*
* @param mediaPackage
* the media package
* @return a list of segments or an empty list if no segments could be found.
*/
private List<Tuple<Long, Long>> getSegments(final MediaPackage mediaPackage) {
List<Tuple<Long, Long>> segments = new ArrayList<>();
for (Catalog smilCatalog : mediaPackage.getCatalogs(adminUIConfiguration.getSmilCatalogFlavor())) {
try {
Smil smil = smilService.fromXml(workspace.get(smilCatalog.getURI())).getSmil();
segments = mergeSegments(segments, getSegmentsFromSmil(smil));
} catch (NotFoundException e) {
logger.warn("File '{}' could not be loaded by workspace service: {}", smilCatalog.getURI(), getStackTrace(e));
} catch (IOException e) {
logger.warn("Reading file '{}' from workspace service failed: {}", smilCatalog.getURI(), getStackTrace(e));
} catch (SmilException e) {
logger.warn("Error while parsing SMIL catalog '{}': {}", smilCatalog.getURI(), getStackTrace(e));
}
}
if (!segments.isEmpty())
return segments;
// Read from silence detection flavors
for (Catalog smilCatalog : mediaPackage.getCatalogs(adminUIConfiguration.getSmilSilenceFlavor())) {
try {
Smil smil = smilService.fromXml(workspace.get(smilCatalog.getURI())).getSmil();
segments = mergeSegments(segments, getSegmentsFromSmil(smil));
} catch (NotFoundException e) {
logger.warn("File '{}' could not be loaded by workspace service: {}", smilCatalog.getURI(), getStackTrace(e));
} catch (IOException e) {
logger.warn("Reading file '{}' from workspace service failed: {}", smilCatalog.getURI(), getStackTrace(e));
} catch (SmilException e) {
logger.warn("Error while parsing SMIL catalog '{}': {}", smilCatalog.getURI(), getStackTrace(e));
}
}
// Check for single segment to ignore
if (segments.size() == 1) {
Tuple<Long, Long> singleSegment = segments.get(0);
if (singleSegment.getA() == 0 && singleSegment.getB() >= mediaPackage.getDuration())
segments.remove(0);
}
return segments;
}
use of org.opencastproject.smil.api.SmilException in project opencast by opencast.
the class VideoEditorWorkflowOperationHandler method resume.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.ResumableWorkflowOperationHandler#resume(org.opencastproject.workflow.api.WorkflowInstance,
* JobContext, java.util.Map)
*/
@Override
public WorkflowOperationResult resume(WorkflowInstance workflowInstance, JobContext context, Map<String, String> properties) throws WorkflowOperationException {
MediaPackage mp = workflowInstance.getMediaPackage();
logger.info("Resume video editor operation for mediapackage {}", mp.getIdentifier().compact());
// Get configuration
WorkflowOperationInstance worflowOperationInstance = workflowInstance.getCurrentOperation();
String sourceTrackFlavorsProperty = StringUtils.trimToNull(worflowOperationInstance.getConfiguration(SOURCE_FLAVORS_PROPERTY));
if (sourceTrackFlavorsProperty == null) {
throw new WorkflowOperationException(format("Required configuration property %s not set.", SOURCE_FLAVORS_PROPERTY));
}
String targetSmilFlavorProperty = StringUtils.trimToNull(worflowOperationInstance.getConfiguration(TARGET_SMIL_FLAVOR_PROPERTY));
if (targetSmilFlavorProperty == null) {
throw new WorkflowOperationException(format("Required configuration property %s not set.", TARGET_SMIL_FLAVOR_PROPERTY));
}
String targetFlavorSybTypeProperty = StringUtils.trimToNull(worflowOperationInstance.getConfiguration(TARGET_FLAVOR_SUBTYPE_PROPERTY));
if (targetFlavorSybTypeProperty == null) {
throw new WorkflowOperationException(format("Required configuration property %s not set.", TARGET_FLAVOR_SUBTYPE_PROPERTY));
}
boolean skipIfNoTrim = BooleanUtils.toBoolean(worflowOperationInstance.getConfiguration(SKIP_NOT_TRIMMED_PROPERTY));
// Get source tracks
TrackSelector trackSelector = new TrackSelector();
for (String flavor : asList(sourceTrackFlavorsProperty)) {
trackSelector.addFlavor(flavor);
}
Collection<Track> sourceTracks = trackSelector.select(mp, false);
if (sourceTracks.isEmpty()) {
throw new WorkflowOperationException(format("No source tracks found in mediapacksge %s with flavors %s.", mp.getIdentifier().compact(), sourceTrackFlavorsProperty));
}
// Get SMIL file
MediaPackageElementFlavor smilTargetFlavor = MediaPackageElementFlavor.parseFlavor(targetSmilFlavorProperty);
Catalog[] smilCatalogs = mp.getCatalogs(smilTargetFlavor);
if (smilCatalogs == null || smilCatalogs.length == 0) {
throw new WorkflowOperationException(format("No SMIL catalog found in mediapackage %s with flavor %s.", mp.getIdentifier().compact(), targetSmilFlavorProperty));
}
File smilFile = null;
Smil smil = null;
try {
smilFile = workspace.get(smilCatalogs[0].getURI());
smil = smilService.fromXml(smilFile).getSmil();
smil = replaceAllTracksWith(smil, sourceTracks.toArray(new Track[sourceTracks.size()]));
InputStream is = null;
try {
is = IOUtils.toInputStream(smil.toXML(), "UTF-8");
// Remove old SMIL
workspace.delete(mp.getIdentifier().compact(), smilCatalogs[0].getIdentifier());
mp.remove(smilCatalogs[0]);
// put modified SMIL into workspace
URI newSmilUri = workspace.put(mp.getIdentifier().compact(), smil.getId(), SMIL_FILE_NAME, is);
Catalog catalog = (Catalog) MediaPackageElementBuilderFactory.newInstance().newElementBuilder().elementFromURI(newSmilUri, MediaPackageElement.Type.Catalog, smilCatalogs[0].getFlavor());
catalog.setIdentifier(smil.getId());
mp.add(catalog);
} catch (Exception ex) {
throw new WorkflowOperationException(ex);
} finally {
IOUtils.closeQuietly(is);
}
} catch (NotFoundException ex) {
throw new WorkflowOperationException(format("Failed to get SMIL catalog %s from mediapackage %s.", smilCatalogs[0].getIdentifier(), mp.getIdentifier().compact()), ex);
} catch (IOException ex) {
throw new WorkflowOperationException(format("Can't open SMIL catalog %s from mediapackage %s.", smilCatalogs[0].getIdentifier(), mp.getIdentifier().compact()), ex);
} catch (SmilException ex) {
throw new WorkflowOperationException(ex);
}
if (skipIfNoTrim) {
// We should not modify the SMIL file as we traverse through its elements, so we make a copy and modify it instead
try {
Smil filteredSmil = smilService.fromXml(smil.toXML()).getSmil();
for (SmilMediaObject element : smil.getBody().getMediaElements()) {
// body should contain par elements
if (element.isContainer()) {
SmilMediaContainer container = (SmilMediaContainer) element;
if (SmilMediaContainer.ContainerType.PAR == container.getContainerType()) {
continue;
}
}
filteredSmil = smilService.removeSmilElement(filteredSmil, element.getId()).getSmil();
}
// one that takes the whole video size
switch(filteredSmil.getBody().getMediaElements().size()) {
case 0:
logger.info("Skipping SMIL job generation for mediapackage '{}', " + "because the SMIL does not define any trimming points", mp.getIdentifier());
return skip(workflowInstance, context);
case 1:
// component represents the whole duration or not, therefore we don't bother to try
if (mp.getDuration() < 0)
break;
SmilMediaContainer parElement = (SmilMediaContainer) filteredSmil.getBody().getMediaElements().get(0);
boolean skip = true;
for (SmilMediaObject elementChild : parElement.getElements()) {
if (!elementChild.isContainer()) {
SmilMediaElement media = (SmilMediaElement) elementChild;
// If they don't represent the whole length, then we break --we have a trimming point
if ((media.getClipBeginMS() != 0) || (media.getClipEndMS() != mp.getDuration())) {
skip = false;
break;
}
}
}
if (skip) {
logger.info("Skipping SMIL job generation for mediapackage '{}', " + "because the trimming points in the SMIL correspond " + "to the beginning and the end of the video", mp.getIdentifier());
return skip(workflowInstance, context);
}
break;
default:
break;
}
} catch (MalformedURLException | SmilException | JAXBException | SAXException e) {
logger.warn("Error parsing input SMIL to determine if it has trimpoints. " + "We will assume it does and go on creating jobs.");
}
}
// Create video edit jobs and run them
List<Job> jobs = null;
try {
logger.info("Create processing jobs for SMIL file: {}", smilCatalogs[0].getIdentifier());
jobs = videoEditorService.processSmil(smil);
if (!waitForStatus(jobs.toArray(new Job[jobs.size()])).isSuccess()) {
throw new WorkflowOperationException(format("Processing SMIL file failed: %s", smilCatalogs[0].getIdentifier()));
}
logger.info("Finished processing of SMIL file: {}", smilCatalogs[0].getIdentifier());
} catch (ProcessFailedException ex) {
throw new WorkflowOperationException(format("Finished processing of SMIL file: %s", smilCatalogs[0].getIdentifier()), ex);
}
// Move edited tracks to work location and set target flavor
Track editedTrack = null;
boolean mpAdded = false;
for (Job job : jobs) {
try {
editedTrack = (Track) MediaPackageElementParser.getFromXml(job.getPayload());
MediaPackageElementFlavor editedTrackFlavor = editedTrack.getFlavor();
editedTrack.setFlavor(new MediaPackageElementFlavor(editedTrackFlavor.getType(), targetFlavorSybTypeProperty));
URI editedTrackNewUri = workspace.moveTo(editedTrack.getURI(), mp.getIdentifier().compact(), editedTrack.getIdentifier(), FilenameUtils.getName(editedTrack.getURI().toString()));
editedTrack.setURI(editedTrackNewUri);
for (Track track : sourceTracks) {
if (track.getFlavor().getType().equals(editedTrackFlavor.getType())) {
mp.addDerived(editedTrack, track);
mpAdded = true;
break;
}
}
if (!mpAdded) {
mp.add(editedTrack);
}
} catch (MediaPackageException ex) {
throw new WorkflowOperationException("Failed to get information about the edited track(s)", ex);
} catch (NotFoundException | IOException | IllegalArgumentException ex) {
throw new WorkflowOperationException("Moving edited track to work location failed.", ex);
} catch (Exception ex) {
throw new WorkflowOperationException(ex);
}
}
logger.info("VideoEdit workflow {} finished", workflowInstance.getId());
return createResult(mp, Action.CONTINUE);
}
use of org.opencastproject.smil.api.SmilException in project opencast by opencast.
the class VideoEditorWorkflowOperationHandler method replaceAllTracksWith.
protected Smil replaceAllTracksWith(Smil smil, Track[] otherTracks) throws SmilException {
SmilResponse smilResponse;
try {
// copy SMIL to work with
smilResponse = smilService.fromXml(smil.toXML());
} catch (Exception ex) {
throw new SmilException("Can not parse SMIL files.");
}
long start;
long end;
// iterate over all elements inside SMIL body
for (SmilMediaObject elem : smil.getBody().getMediaElements()) {
start = -1L;
end = -1L;
// body should contain par elements (container)
if (elem.isContainer()) {
// iterate over all elements in container
for (SmilMediaObject child : ((SmilMediaContainer) elem).getElements()) {
// second depth should contain media elements like audio or video
if (!child.isContainer() && child instanceof SmilMediaElement) {
SmilMediaElement media = (SmilMediaElement) child;
start = media.getClipBeginMS();
end = media.getClipEndMS();
// remove it
smilResponse = smilService.removeSmilElement(smilResponse.getSmil(), media.getId());
}
}
if (start != -1L && end != -1L) {
// add the new tracks inside
smilResponse = smilService.addClips(smilResponse.getSmil(), elem.getId(), otherTracks, start, end - start);
}
} else if (elem instanceof SmilMediaElement) {
throw new SmilException("Media elements inside SMIL body are not supported yet.");
}
}
return smilResponse.getSmil();
}
use of org.opencastproject.smil.api.SmilException in project opencast by opencast.
the class SmilServiceImpl method addClip.
/**
* {@inheritDoc}
*/
@Override
public SmilResponse addClip(Smil smil, String parentId, Track track, long start, long duration, String pgId) throws SmilException {
if (start < 0) {
throw new SmilException("Start position should be positive.");
}
if (duration < 0) {
throw new SmilException("Duration should be positive.");
}
if (track.getURI() == null) {
throw new SmilException("Track URI isn't set.");
}
if (track.getFlavor() == null) {
throw new SmilException("Track flavor isn't set.");
}
if (track.getDuration() != null) {
if (!track.hasAudio() && !track.hasVideo()) {
throw new SmilException("Track should have at least one audio or video stream.");
}
if (start >= track.getDuration()) {
throw new SmilException("Start value is bigger than track length.");
}
if (start + duration > track.getDuration()) {
duration = track.getDuration() - start;
}
}
SmilMediaParamGroup trackParamGroup = null;
for (SmilMediaParamGroup paramGroup : smil.getHead().getParamGroups()) {
// support for adding multiple tracks to the same param group
if (pgId != null && paramGroup.getId().equals(pgId.trim())) {
trackParamGroup = paramGroup;
break;
}
SmilMediaParam param = ((SmilMediaParamGroupImpl) paramGroup).getParamByName(SmilMediaParam.PARAM_NAME_TRACK_ID);
if (param != null && param.getValue().equals(track.getIdentifier())) {
trackParamGroup = paramGroup;
break;
}
}
boolean newTrack = trackParamGroup == null;
if (newTrack) {
// add paramgroup for new Track
trackParamGroup = new SmilMediaParamGroupImpl();
((SmilMediaParamGroupImpl) trackParamGroup).addParam(SmilMediaParam.PARAM_NAME_TRACK_ID, track.getIdentifier());
((SmilMediaParamGroupImpl) trackParamGroup).addParam(SmilMediaParam.PARAM_NAME_TRACK_SRC, track.getURI().toString());
((SmilMediaParamGroupImpl) trackParamGroup).addParam(SmilMediaParam.PARAM_NAME_TRACK_FLAVOR, track.getFlavor().toString());
((SmilHeadImpl) smil.getHead()).addParamGroup(trackParamGroup);
}
SmilMeta durationMeta = null;
for (SmilMeta meta : smil.getHead().getMetas()) {
if (SmilMeta.SMIL_META_NAME_TRACK_DURATION.equals(meta.getName())) {
durationMeta = meta;
break;
}
}
if (track.getDuration() != null) {
// set track-duration meta if not set or the trackduration is longer than old value
if (durationMeta == null) {
((SmilHeadImpl) smil.getHead()).addMeta(SmilMeta.SMIL_META_NAME_TRACK_DURATION, String.format("%dms", track.getDuration()));
} else {
long durationOld = Long.parseLong(durationMeta.getContent().replace("ms", ""));
if (track.getDuration() > durationOld) {
((SmilHeadImpl) smil.getHead()).addMeta(SmilMeta.SMIL_META_NAME_TRACK_DURATION, String.format("%dms", track.getDuration()));
}
}
}
SmilMediaElementImpl media = null;
if (track.hasVideo()) {
media = new SmilMediaVideoImpl(track.getURI(), start, start + duration);
} else if (track.hasAudio()) {
media = new SmilMediaAudioImpl(track.getURI(), start, start + duration);
} else {
media = new SmilMediaReferenceImpl(track.getURI(), start, start + duration);
}
media.setParamGroup(trackParamGroup.getId());
if (parentId == null || "".equals(parentId)) {
parentId = smil.getBody().getId();
}
// add new media element
((SmilBodyImpl) smil.getBody()).addMediaElement(media, parentId);
if (newTrack) {
return new SmilResponseImpl(smil, new SmilObject[] { media, trackParamGroup });
} else {
return new SmilResponseImpl(smil, media);
}
}
use of org.opencastproject.smil.api.SmilException in project opencast by opencast.
the class SmilResponseImplTest method testGetEntity.
/**
* Test of getEntity method, of class SmilResponseImpl.
*/
@Test
public void testGetEntity() throws Exception {
Smil smil = new SmilImpl();
SmilResponse response = new SmilResponseImpl(smil);
try {
response.getEntity();
fail("getEntity should fail, if entity count is zero");
} catch (SmilException ex) {
}
response = new SmilResponseImpl(smil, smil.getBody());
try {
assertSame(smil.getBody(), response.getEntity());
assertSame(1, response.getEntities().length);
assertSame(smil.getBody(), response.getEntities()[0]);
} catch (SmilException ex) {
fail("getEntity should return the entity");
}
response = new SmilResponseImpl(smil, new SmilObject[] { smil.getHead(), smil.getBody() });
try {
response.getEntity();
fail("get entity should fail if there are more then one entities set.");
} catch (SmilException ex) {
}
}
Aggregations