use of org.opencastproject.mediapackage.MediaPackageException in project opencast by opencast.
the class ComposerServiceImpl method parallelEncode.
/**
* Encodes audio and video track to a file. If both an audio and a video track are given, they are muxed together into
* one movie container.
*
* @param job
* Job in which context the encoding is done
* @param mediaTrack
* Source track
* @param profileId
* the encoding profile
* @return the encoded track or none if the operation does not return a track. This may happen for example when doing
* two pass encodings where the first pass only creates metadata for the second one
* @throws EncoderException
* if encoding fails
*/
private List<Track> parallelEncode(Job job, Track mediaTrack, String profileId) throws EncoderException, MediaPackageException {
if (job == null) {
throw new EncoderException("The Job parameter must not be null");
}
// Get the tracks and make sure they exist
final File mediaFile = loadTrackIntoWorkspace(job, "source", mediaTrack);
// Create the engine
final EncodingProfile profile = getProfile(profileId);
final EncoderEngine encoderEngine = getEncoderEngine();
// List of encoded tracks
LinkedList<Track> encodedTracks = new LinkedList<>();
// Do the work
int i = 0;
Map<String, File> source = new HashMap<>();
source.put("video", mediaFile);
List<File> outputFiles = encoderEngine.process(source, profile, null);
activeEncoder.remove(encoderEngine);
for (File encodingOutput : outputFiles) {
// Put the file in the workspace
URI returnURL;
final String targetTrackId = idBuilder.createNew().toString();
try (InputStream in = new FileInputStream(encodingOutput)) {
returnURL = workspace.putInCollection(COLLECTION, job.getId() + "-" + i + "." + FilenameUtils.getExtension(encodingOutput.getAbsolutePath()), in);
logger.info("Copied the encoded file to the workspace at {}", returnURL);
if (encodingOutput.delete()) {
logger.info("Deleted the local copy of the encoded file at {}", encodingOutput.getAbsolutePath());
} else {
logger.warn("Unable to delete the encoding output at {}", encodingOutput);
}
} catch (Exception e) {
throw new EncoderException("Unable to put the encoded file into the workspace", e);
}
// Have the encoded track inspected and return the result
Job inspectionJob = inspect(job, returnURL);
Track inspectedTrack = (Track) MediaPackageElementParser.getFromXml(inspectionJob.getPayload());
inspectedTrack.setIdentifier(targetTrackId);
List<String> tags = profile.getTags();
for (String tag : tags) {
if (encodingOutput.getName().endsWith(profile.getSuffix(tag)))
inspectedTrack.addTag(tag);
}
encodedTracks.add(inspectedTrack);
i++;
}
return encodedTracks;
}
use of org.opencastproject.mediapackage.MediaPackageException in project opencast by opencast.
the class ComposerServiceImpl method trim.
/**
* Trims the given track using the encoding profile <code>profileId</code> and the given starting point and duration
* in miliseconds.
*
* @param job
* the associated job
* @param sourceTrack
* the source track
* @param profileId
* the encoding profile identifier
* @param start
* the trimming in-point in millis
* @param duration
* the trimming duration in millis
* @return the trimmed track or none if the operation does not return a track. This may happen for example when doing
* two pass encodings where the first pass only creates metadata for the second one
* @throws EncoderException
* if trimming fails
*/
private Option<Track> trim(Job job, Track sourceTrack, String profileId, long start, long duration) throws EncoderException {
String targetTrackId = idBuilder.createNew().toString();
// Get the track and make sure it exists
final File trackFile = loadTrackIntoWorkspace(job, "source", sourceTrack);
// Get the encoding profile
final EncodingProfile profile = getProfile(job, profileId);
// Create the engine
final EncoderEngine encoderEngine = getEncoderEngine();
File output;
try {
output = encoderEngine.trim(trackFile, profile, start, duration, null);
} catch (EncoderException e) {
Map<String, String> params = new HashMap<>();
params.put("track", sourceTrack.getURI().toString());
params.put("profile", profile.getIdentifier());
params.put("start", Long.toString(start));
params.put("duration", Long.toString(duration));
incident().recordFailure(job, TRIMMING_FAILED, e, params, detailsFor(e, encoderEngine));
throw e;
} finally {
activeEncoder.remove(encoderEngine);
}
// trim did not return a file
if (!output.exists() || output.length() == 0)
return none();
// Put the file in the workspace
URI workspaceURI = putToCollection(job, output, "trimmed file");
// Have the encoded track inspected and return the result
Job inspectionJob = inspect(job, workspaceURI);
try {
Track inspectedTrack = (Track) MediaPackageElementParser.getFromXml(inspectionJob.getPayload());
inspectedTrack.setIdentifier(targetTrackId);
return some(inspectedTrack);
} catch (MediaPackageException e) {
throw new EncoderException(e);
}
}
use of org.opencastproject.mediapackage.MediaPackageException in project opencast by opencast.
the class ComposerServiceImpl method composite.
private Option<Track> composite(Job job, Dimension compositeTrackSize, LaidOutElement<Track> lowerLaidOutElement, Option<LaidOutElement<Track>> upperLaidOutElement, Option<LaidOutElement<Attachment>> watermarkOption, String profileId, String backgroundColor) throws EncoderException, MediaPackageException {
// Get the encoding profile
final EncodingProfile profile = getProfile(job, profileId);
// Create the engine
final EncoderEngine encoderEngine = getEncoderEngine();
final String targetTrackId = idBuilder.createNew().toString();
Option<File> upperVideoFile = Option.none();
try {
// Get the tracks and make sure they exist
final File lowerVideoFile = loadTrackIntoWorkspace(job, "lower video", lowerLaidOutElement.getElement());
if (upperLaidOutElement.isSome()) {
upperVideoFile = Option.option(loadTrackIntoWorkspace(job, "upper video", upperLaidOutElement.get().getElement()));
}
File watermarkFile = null;
if (watermarkOption.isSome()) {
try {
watermarkFile = workspace.get(watermarkOption.get().getElement().getURI());
} catch (NotFoundException e) {
incident().recordFailure(job, WORKSPACE_GET_NOT_FOUND, e, getWorkspaceMediapackageParams("watermark image", watermarkOption.get().getElement()), NO_DETAILS);
throw new EncoderException("Requested watermark image " + watermarkOption.get().getElement() + " is not found");
} catch (IOException e) {
incident().recordFailure(job, WORKSPACE_GET_IO_EXCEPTION, e, getWorkspaceMediapackageParams("watermark image", watermarkOption.get().getElement()), NO_DETAILS);
throw new EncoderException("Unable to access right watermark image " + watermarkOption.get().getElement());
}
if (upperLaidOutElement.isSome()) {
logger.info("Composing lower video track {} {} and upper video track {} {} including watermark {} {} into {}", lowerLaidOutElement.getElement().getIdentifier(), lowerLaidOutElement.getElement().getURI(), upperLaidOutElement.get().getElement().getIdentifier(), upperLaidOutElement.get().getElement().getURI(), watermarkOption.get().getElement().getIdentifier(), watermarkOption.get().getElement().getURI(), targetTrackId);
} else {
logger.info("Composing video track {} {} including watermark {} {} into {}", lowerLaidOutElement.getElement().getIdentifier(), lowerLaidOutElement.getElement().getURI(), watermarkOption.get().getElement().getIdentifier(), watermarkOption.get().getElement().getURI(), targetTrackId);
}
} else {
if (upperLaidOutElement.isSome()) {
logger.info("Composing lower video track {} {} and upper video track {} {} into {}", lowerLaidOutElement.getElement().getIdentifier(), lowerLaidOutElement.getElement().getURI(), upperLaidOutElement.get().getElement().getIdentifier(), upperLaidOutElement.get().getElement().getURI(), targetTrackId);
} else {
logger.info("Composing video track {} {} into {}", lowerLaidOutElement.getElement().getIdentifier(), lowerLaidOutElement.getElement().getURI(), targetTrackId);
}
}
// Creating video filter command
final String compositeCommand = buildCompositeCommand(compositeTrackSize, lowerLaidOutElement, upperLaidOutElement, upperVideoFile, watermarkOption, watermarkFile, backgroundColor);
Map<String, String> properties = new HashMap<>();
properties.put(EncoderEngine.CMD_SUFFIX + ".compositeCommand", compositeCommand);
List<File> output;
try {
Map<String, File> source = new HashMap<>();
if (upperVideoFile.isSome()) {
source.put("audio", upperVideoFile.get());
}
source.put("video", lowerVideoFile);
output = encoderEngine.process(source, profile, properties);
} catch (EncoderException e) {
Map<String, String> params = new HashMap<>();
if (upperLaidOutElement.isSome()) {
params.put("upper", upperLaidOutElement.get().getElement().getURI().toString());
}
params.put("lower", lowerLaidOutElement.getElement().getURI().toString());
if (watermarkFile != null)
params.put("watermark", watermarkOption.get().getElement().getURI().toString());
params.put("profile", profile.getIdentifier());
params.put("properties", properties.toString());
incident().recordFailure(job, COMPOSITE_FAILED, e, params, detailsFor(e, encoderEngine));
throw e;
} finally {
activeEncoder.remove(encoderEngine);
}
// We expect one file as output
if (output.size() != 1) {
// Ensure we do not leave behind old files in the workspace
for (File file : output) {
FileUtils.deleteQuietly(file);
}
throw new EncoderException("Composite does not support multiple files as output");
}
// Put the file in the workspace
URI workspaceURI = putToCollection(job, output.get(0), "compound file");
// Have the compound track inspected and return the result
Job inspectionJob = inspect(job, workspaceURI);
Track inspectedTrack = (Track) MediaPackageElementParser.getFromXml(inspectionJob.getPayload());
inspectedTrack.setIdentifier(targetTrackId);
if (profile.getMimeType() != null)
inspectedTrack.setMimeType(MimeTypes.parseMimeType(profile.getMimeType()));
return some(inspectedTrack);
} catch (Exception e) {
if (upperLaidOutElement.isSome()) {
logger.warn("Error composing {} and {}: {}", lowerLaidOutElement.getElement(), upperLaidOutElement.get().getElement(), getStackTrace(e));
} else {
logger.warn("Error composing {}: {}", lowerLaidOutElement.getElement(), getStackTrace(e));
}
if (e instanceof EncoderException) {
throw (EncoderException) e;
} else {
throw new EncoderException(e);
}
}
}
use of org.opencastproject.mediapackage.MediaPackageException in project opencast by opencast.
the class ComposerServiceRemoteImpl method concat.
@Override
public Job concat(String profileId, Dimension outputDimension, float outputFrameRate, Track... tracks) throws EncoderException, MediaPackageException {
HttpPost post = new HttpPost("/concat");
try {
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
params.add(new BasicNameValuePair("profileId", profileId));
if (outputDimension != null)
params.add(new BasicNameValuePair("outputDimension", Serializer.json(outputDimension).toJson()));
params.add(new BasicNameValuePair("outputFrameRate", String.format(Locale.US, "%f", outputFrameRate)));
params.add(new BasicNameValuePair("sourceTracks", MediaPackageElementParser.getArrayAsXml(Arrays.asList(tracks))));
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (Exception e) {
throw new EncoderException(e);
}
HttpResponse response = null;
try {
response = getResponse(post);
if (response != null) {
Job r = JobParser.parseJob(response.getEntity().getContent());
logger.info("Concat video job {} started on a remote composer", r.getId());
return r;
}
} catch (Exception e) {
throw new EncoderException(e);
} finally {
closeConnection(response);
}
throw new EncoderException("Unable to concat videos from tracks " + tracks + " using the remote composer service proxy");
}
use of org.opencastproject.mediapackage.MediaPackageException in project opencast by opencast.
the class ComposerServiceRemoteImpl method composite.
@Override
public Job composite(Dimension compositeTrackSize, Option<LaidOutElement<Track>> upperTrack, LaidOutElement<Track> lowerTrack, Option<LaidOutElement<Attachment>> watermark, String profileId, String background) throws EncoderException, MediaPackageException {
HttpPost post = new HttpPost("/composite");
try {
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
params.add(new BasicNameValuePair("compositeSize", Serializer.json(compositeTrackSize).toJson()));
params.add(new BasicNameValuePair("lowerTrack", MediaPackageElementParser.getAsXml(lowerTrack.getElement())));
params.add(new BasicNameValuePair("lowerLayout", Serializer.json(lowerTrack.getLayout()).toJson()));
if (upperTrack.isSome()) {
params.add(new BasicNameValuePair("upperTrack", MediaPackageElementParser.getAsXml(upperTrack.get().getElement())));
params.add(new BasicNameValuePair("upperLayout", Serializer.json(upperTrack.get().getLayout()).toJson()));
}
if (watermark.isSome()) {
params.add(new BasicNameValuePair("watermarkAttachment", MediaPackageElementParser.getAsXml(watermark.get().getElement())));
params.add(new BasicNameValuePair("watermarkLayout", Serializer.json(watermark.get().getLayout()).toJson()));
}
params.add(new BasicNameValuePair("profileId", profileId));
params.add(new BasicNameValuePair("background", background));
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (Exception e) {
throw new EncoderException(e);
}
HttpResponse response = null;
try {
response = getResponse(post);
if (response != null) {
Job r = JobParser.parseJob(response.getEntity().getContent());
logger.info("Composite video job {} started on a remote composer", r.getId());
return r;
}
} catch (Exception e) {
throw new EncoderException(e);
} finally {
closeConnection(response);
}
if (upperTrack.isSome()) {
throw new EncoderException("Unable to composite video from track " + lowerTrack.getElement() + " and " + upperTrack.get().getElement() + " using the remote composer service proxy");
} else {
throw new EncoderException("Unable to composite video from track " + lowerTrack.getElement() + " using the remote composer service proxy");
}
}
Aggregations