Search in sources :

Example 1 with AnimateServiceException

use of org.opencastproject.animate.api.AnimateServiceException in project opencast by opencast.

the class AnimateServiceImpl method process.

/**
 * {@inheritDoc}
 *
 * @see org.opencastproject.job.api.AbstractJobProducer#process(org.opencastproject.job.api.Job)
 */
@Override
protected String process(Job job) throws Exception {
    logger.debug("Started processing job {}", job.getId());
    if (!OPERATION.equals(job.getOperation())) {
        throw new ServiceRegistryException(String.format("This service can't handle operations of type '%s'", job.getOperation()));
    }
    List<String> arguments = job.getArguments();
    URI animation = new URI(arguments.get(0));
    Gson gson = new Gson();
    Map<String, String> metadata = gson.fromJson(arguments.get(1), stringMapType);
    List<String> options = gson.fromJson(arguments.get(2), stringListType);
    // filter animation and get new, custom input file
    File input = customAnimation(job, animation, metadata);
    // prepare output file
    File output = new File(workspace.rootDirectory(), String.format("animate/%d/%s.%s", job.getId(), FilenameUtils.getBaseName(animation.getPath()), "mkv"));
    FileUtils.forceMkdirParent(output);
    // create animation process.
    final List<String> command = new ArrayList<>();
    command.add(synfigBinary);
    command.add("-i");
    command.add(input.getAbsolutePath());
    command.add("-o");
    command.add(output.getAbsolutePath());
    command.addAll(options);
    logger.info("Executing animation command: {}", command);
    Process process = null;
    try {
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true);
        process = processBuilder.start();
        // print synfig (+ffmpeg) output
        try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = in.readLine()) != null) {
                logger.debug("Synfig: {}", line);
            }
        }
        // wait until the task is finished
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            throw new AnimateServiceException(String.format("Synfig exited abnormally with status %d (command: %s)", exitCode, command));
        }
        if (!output.isFile()) {
            throw new AnimateServiceException("Synfig produced no output");
        }
        logger.info("Animation generated successfully: {}", output);
    } catch (Exception e) {
        // Ensure temporary data are removed
        FileUtils.deleteQuietly(output.getParentFile());
        logger.debug("Removed output directory of failed animation process: {}", output.getParentFile());
        throw new AnimateServiceException(e);
    } finally {
        IoSupport.closeQuietly(process);
        FileUtils.deleteQuietly(input);
    }
    URI uri = workspace.putInCollection("animate-" + job.getId(), output.getName(), new FileInputStream(output));
    FileUtils.deleteQuietly(new File(workspace.rootDirectory(), String.format("animate/%d", job.getId())));
    return uri.toString();
}
Also used : InputStreamReader(java.io.InputStreamReader) ArrayList(java.util.ArrayList) Gson(com.google.gson.Gson) URI(java.net.URI) ServiceRegistryException(org.opencastproject.serviceregistry.api.ServiceRegistryException) ServiceRegistryException(org.opencastproject.serviceregistry.api.ServiceRegistryException) AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) NotFoundException(org.opencastproject.util.NotFoundException) ConfigurationException(org.opencastproject.util.ConfigurationException) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) BufferedReader(java.io.BufferedReader) File(java.io.File)

Example 2 with AnimateServiceException

use of org.opencastproject.animate.api.AnimateServiceException in project opencast by opencast.

the class AnimateServiceImpl method animate.

@Override
public Job animate(URI animation, Map<String, String> metadata, List<String> arguments) throws AnimateServiceException {
    Gson gson = new Gson();
    List<String> jobArguments = Arrays.asList(animation.toString(), gson.toJson(metadata), gson.toJson(arguments));
    try {
        logger.debug("Create animate service job");
        return serviceRegistry.createJob(JOB_TYPE, OPERATION, jobArguments, jobLoad);
    } catch (ServiceRegistryException e) {
        throw new AnimateServiceException(e);
    }
}
Also used : AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) Gson(com.google.gson.Gson) ServiceRegistryException(org.opencastproject.serviceregistry.api.ServiceRegistryException)

Example 3 with AnimateServiceException

use of org.opencastproject.animate.api.AnimateServiceException in project opencast by opencast.

the class AnimateWorkflowOperationHandler method start.

/**
 * {@inheritDoc}
 *
 * @see
 * org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance,
 * org.opencastproject.job.api.JobContext)
 */
@Override
public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
    MediaPackage mediaPackage = workflowInstance.getMediaPackage();
    logger.info("Start animate workflow operation for media package {}", mediaPackage);
    WorkflowOperationInstance operation = workflowInstance.getCurrentOperation();
    List<String> arguments;
    // Check required options
    final File animationFile = new File(StringUtils.trimToEmpty(operation.getConfiguration(ANIMATION_FILE_PROPERTY)));
    if (!animationFile.isFile()) {
        throw new WorkflowOperationException(String.format("Animation file `%s` does not exist", animationFile));
    }
    URI animation = animationFile.toURI();
    final MediaPackageElementFlavor targetFlavor;
    try {
        targetFlavor = MediaPackageElementFlavor.parseFlavor(StringUtils.trimToNull(operation.getConfiguration(TARGET_FLAVOR_PROPERTY)));
    } catch (IllegalArgumentException e) {
        throw new WorkflowOperationException("Invalid target flavor", e);
    }
    // Get optional options
    String targetTagsProperty = StringUtils.trimToNull(operation.getConfiguration(TARGET_TAGS_PROPERTY));
    // Check if we have custom command line options
    String cmd = operation.getConfiguration(COMMANDLINE_ARGUMENTS_PROPERTY);
    if (StringUtils.isNotEmpty(cmd)) {
        arguments = Arrays.asList(StringUtils.split(cmd));
    } else {
        // set default encoding
        arguments = new ArrayList<>();
        arguments.add("-t");
        arguments.add("ffmpeg");
        arguments.add("--video-codec");
        arguments.add("libx264-lossless");
        arguments.add("--video-bitrate");
        arguments.add("10000");
        addArgumentIfExists(operation, arguments, WIDTH_PROPERTY, "-w");
        addArgumentIfExists(operation, arguments, HEIGHT_PROPERTY, "-h");
        addArgumentIfExists(operation, arguments, FPS_PROPERTY, "--fps");
    }
    final Map<String, String> metadata = getMetadata(mediaPackage);
    Job job;
    try {
        job = animateService.animate(animation, metadata, arguments);
    } catch (AnimateServiceException e) {
        throw new WorkflowOperationException(String.format("Rendering animation from '%s' in media package '%s' failed", animation, mediaPackage), e);
    }
    if (!waitForStatus(job).isSuccess()) {
        throw new WorkflowOperationException(String.format("Animate job for media package '%s' failed", mediaPackage));
    }
    // put animated clip into media package
    try {
        URI output = new URI(job.getPayload());
        String id = UUID.randomUUID().toString();
        InputStream in = workspace.read(output);
        URI uri = workspace.put(mediaPackage.getIdentifier().toString(), id, FilenameUtils.getName(output.getPath()), in);
        TrackImpl track = new TrackImpl();
        track.setIdentifier(id);
        track.setFlavor(targetFlavor);
        track.setURI(uri);
        Job inspection = mediaInspectionService.enrich(track, true);
        if (!waitForStatus(inspection).isSuccess()) {
            throw new AnimateServiceException(String.format("Animating %s failed", animation));
        }
        track = (TrackImpl) MediaPackageElementParser.getFromXml(inspection.getPayload());
        // add track to media package
        for (String tag : asList(targetTagsProperty)) {
            track.addTag(tag);
        }
        mediaPackage.add(track);
        workspace.delete(output);
    } catch (Exception e) {
        throw new WorkflowOperationException("Error handling animation service output", e);
    }
    try {
        workspace.cleanup(mediaPackage.getIdentifier());
    } catch (IOException e) {
        throw new WorkflowOperationException(e);
    }
    logger.info("Animate workflow operation for media package {} completed", mediaPackage);
    return createResult(mediaPackage, WorkflowOperationResult.Action.CONTINUE);
}
Also used : InputStream(java.io.InputStream) TrackImpl(org.opencastproject.mediapackage.track.TrackImpl) IOException(java.io.IOException) URI(java.net.URI) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) IOException(java.io.IOException) WorkflowOperationInstance(org.opencastproject.workflow.api.WorkflowOperationInstance) AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) MediaPackage(org.opencastproject.mediapackage.MediaPackage) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) Job(org.opencastproject.job.api.Job) File(java.io.File)

Example 4 with AnimateServiceException

use of org.opencastproject.animate.api.AnimateServiceException in project opencast by opencast.

the class AnimateServiceRestEndpoint method animate.

@POST
@Produces(MediaType.TEXT_XML)
@Path("animate")
@RestQuery(name = "animate", description = "Create animates video clip", restParameters = { @RestParameter(name = "animation", isRequired = true, type = STRING, description = "Location of to the animation"), @RestParameter(name = "arguments", isRequired = true, type = STRING, description = "Synfig command line arguments as JSON array"), @RestParameter(name = "metadata", isRequired = true, type = STRING, description = "Metadata for replacement as JSON object") }, reponses = { @RestResponse(description = "Animation created successfully", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "Invalid data", responseCode = HttpServletResponse.SC_BAD_REQUEST), @RestResponse(description = "Internal error", responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR) }, returnDescription = "Returns the path to the generated animation video")
public Response animate(@FormParam("animation") String animation, @FormParam("arguments") String argumentsString, @FormParam("metadata") String metadataString) {
    Gson gson = new Gson();
    try {
        Map<String, String> metadata = gson.fromJson(metadataString, stringMapType);
        List<String> arguments = gson.fromJson(argumentsString, stringListType);
        logger.debug("Start animation");
        Job job = animateService.animate(new URI(animation), metadata, arguments);
        return Response.ok(new JaxbJob(job)).build();
    } catch (JsonSyntaxException | URISyntaxException | NullPointerException e) {
        logger.debug("Invalid data passed to REST endpoint:\nanimation: {}\nmetadata: {}\narguments: {})", animation, metadataString, argumentsString);
        return Response.status(Response.Status.BAD_REQUEST).build();
    } catch (AnimateServiceException e) {
        logger.error("Error animating file {}", animation, e);
        return Response.serverError().build();
    }
}
Also used : JsonSyntaxException(com.google.gson.JsonSyntaxException) AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) JaxbJob(org.opencastproject.job.api.JaxbJob) Gson(com.google.gson.Gson) URISyntaxException(java.net.URISyntaxException) JaxbJob(org.opencastproject.job.api.JaxbJob) Job(org.opencastproject.job.api.Job) URI(java.net.URI) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Produces(javax.ws.rs.Produces) RestQuery(org.opencastproject.util.doc.rest.RestQuery)

Example 5 with AnimateServiceException

use of org.opencastproject.animate.api.AnimateServiceException in project opencast by opencast.

the class AnimateServiceRemoteImpl method animate.

@Override
public Job animate(URI animation, Map<String, String> metadata, List<String> options) throws AnimateServiceException {
    // serialize arguments and metadata
    String metadataJson = gson.toJson(metadata);
    String optionJson = gson.toJson(options);
    // Build form parameters
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("animation", animation.toString()));
    params.add(new BasicNameValuePair("arguments", optionJson));
    params.add(new BasicNameValuePair("metadata", metadataJson));
    logger.info("Animating {}", animation);
    HttpResponse response = null;
    try {
        HttpPost post = new HttpPost("/animate");
        post.setEntity(new UrlEncodedFormEntity(params));
        response = getResponse(post);
        if (response == null) {
            throw new AnimateServiceException("No response from service");
        }
        Job receipt = JobParser.parseJob(response.getEntity().getContent());
        logger.info("Completed animating {}", animation);
        return receipt;
    } catch (IOException e) {
        throw new AnimateServiceException("Failed building service request", e);
    } finally {
        closeConnection(response);
    }
}
Also used : BasicNameValuePair(org.apache.http.message.BasicNameValuePair) NameValuePair(org.apache.http.NameValuePair) HttpPost(org.apache.http.client.methods.HttpPost) AnimateServiceException(org.opencastproject.animate.api.AnimateServiceException) BasicNameValuePair(org.apache.http.message.BasicNameValuePair) ArrayList(java.util.ArrayList) HttpResponse(org.apache.http.HttpResponse) UrlEncodedFormEntity(org.apache.http.client.entity.UrlEncodedFormEntity) IOException(java.io.IOException) Job(org.opencastproject.job.api.Job)

Aggregations

AnimateServiceException (org.opencastproject.animate.api.AnimateServiceException)5 Gson (com.google.gson.Gson)3 IOException (java.io.IOException)3 URI (java.net.URI)3 Job (org.opencastproject.job.api.Job)3 File (java.io.File)2 ArrayList (java.util.ArrayList)2 ServiceRegistryException (org.opencastproject.serviceregistry.api.ServiceRegistryException)2 JsonSyntaxException (com.google.gson.JsonSyntaxException)1 BufferedReader (java.io.BufferedReader)1 FileInputStream (java.io.FileInputStream)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 URISyntaxException (java.net.URISyntaxException)1 POST (javax.ws.rs.POST)1 Path (javax.ws.rs.Path)1 Produces (javax.ws.rs.Produces)1 HttpResponse (org.apache.http.HttpResponse)1 NameValuePair (org.apache.http.NameValuePair)1 UrlEncodedFormEntity (org.apache.http.client.entity.UrlEncodedFormEntity)1