Search in sources :

Example 1 with WaveformServiceException

use of org.opencastproject.waveform.api.WaveformServiceException in project opencast by opencast.

the class WaveformServiceImpl method extractWaveform.

/**
 * Create and run waveform extraction ffmpeg command.
 *
 * @param track source audio/video track with at least one audio channel
 * @return waveform image attachment
 * @throws WaveformServiceException if processing fails
 */
private Attachment extractWaveform(Track track) throws WaveformServiceException {
    if (!track.hasAudio()) {
        throw new WaveformServiceException("Track has no audio");
    }
    // copy source file into workspace
    File mediaFile;
    try {
        mediaFile = workspace.get(track.getURI());
    } catch (NotFoundException e) {
        throw new WaveformServiceException("Error finding the media file in the workspace", e);
    } catch (IOException e) {
        throw new WaveformServiceException("Error reading the media file in the workspace", e);
    }
    String waveformFilePath = FilenameUtils.removeExtension(mediaFile.getAbsolutePath()).concat('-' + track.getIdentifier()).concat("-waveform.png");
    // create ffmpeg command
    String[] command = new String[] { binary, "-nostats", "-i", mediaFile.getAbsolutePath(), "-lavfi", createWaveformFilter(track), "-an", "-vn", "-sn", "-y", waveformFilePath };
    logger.debug("Start waveform ffmpeg process: {}", StringUtils.join(command, " "));
    logger.info("Create waveform image file for track '{}' at {}", track.getIdentifier(), waveformFilePath);
    // run ffmpeg
    ProcessBuilder pb = new ProcessBuilder(command);
    pb.redirectErrorStream(true);
    Process ffmpegProcess = null;
    int exitCode = 1;
    BufferedReader errStream = null;
    try {
        ffmpegProcess = pb.start();
        errStream = new BufferedReader(new InputStreamReader(ffmpegProcess.getInputStream()));
        String line = errStream.readLine();
        while (line != null) {
            logger.debug(line);
            line = errStream.readLine();
        }
        exitCode = ffmpegProcess.waitFor();
    } catch (IOException ex) {
        throw new WaveformServiceException("Start ffmpeg process failed", ex);
    } catch (InterruptedException ex) {
        throw new WaveformServiceException("Waiting for encoder process exited was interrupted unexpectly", ex);
    } finally {
        IoSupport.closeQuietly(ffmpegProcess);
        IoSupport.closeQuietly(errStream);
        if (exitCode != 0) {
            try {
                FileUtils.forceDelete(new File(waveformFilePath));
            } catch (IOException e) {
            // it is ok, no output file was generated by ffmpeg
            }
        }
    }
    if (exitCode != 0)
        throw new WaveformServiceException("The encoder process exited abnormally with exit code " + exitCode);
    // put waveform image into workspace
    FileInputStream waveformFileInputStream = null;
    URI waveformFileUri;
    try {
        waveformFileInputStream = new FileInputStream(waveformFilePath);
        waveformFileUri = workspace.putInCollection(COLLECTION_ID, FilenameUtils.getName(waveformFilePath), waveformFileInputStream);
        logger.info("Copied the created waveform to the workspace {}", waveformFileUri);
    } catch (FileNotFoundException ex) {
        throw new WaveformServiceException(String.format("Waveform image file '%s' not found", waveformFilePath), ex);
    } catch (IOException ex) {
        throw new WaveformServiceException(String.format("Can't write waveform image file '%s' to workspace", waveformFilePath), ex);
    } catch (IllegalArgumentException ex) {
        throw new WaveformServiceException(ex);
    } finally {
        IoSupport.closeQuietly(waveformFileInputStream);
        logger.info("Deleted local waveform image file at {}", waveformFilePath);
        FileUtils.deleteQuietly(new File(waveformFilePath));
    }
    // create media package element
    MediaPackageElementBuilder mpElementBuilder = MediaPackageElementBuilderFactory.newInstance().newElementBuilder();
    // it is up to the workflow operation handler to set the attachment flavor
    Attachment waveformMpe = (Attachment) mpElementBuilder.elementFromURI(waveformFileUri, Type.Attachment, track.getFlavor());
    waveformMpe.setIdentifier(IdBuilderFactory.newInstance().newIdBuilder().createNew().compact());
    return waveformMpe;
}
Also used : InputStreamReader(java.io.InputStreamReader) FileNotFoundException(java.io.FileNotFoundException) NotFoundException(org.opencastproject.util.NotFoundException) FileNotFoundException(java.io.FileNotFoundException) Attachment(org.opencastproject.mediapackage.Attachment) IOException(java.io.IOException) URI(java.net.URI) FileInputStream(java.io.FileInputStream) MediaPackageElementBuilder(org.opencastproject.mediapackage.MediaPackageElementBuilder) WaveformServiceException(org.opencastproject.waveform.api.WaveformServiceException) BufferedReader(java.io.BufferedReader) File(java.io.File)

Example 2 with WaveformServiceException

use of org.opencastproject.waveform.api.WaveformServiceException in project opencast by opencast.

the class WaveformServiceRemote method createWaveformImage.

/**
 * Takes the given track and returns the job that will create an waveform image using a remote service.
 *
 * @param sourceTrack the track to create waveform image from
 * @return a job that will create a waveform image
 * @throws MediaPackageException if the serialization of the given track fails
 * @throws WaveformServiceException if the job can't be created for any reason
 */
@Override
public Job createWaveformImage(Track sourceTrack) throws MediaPackageException, WaveformServiceException {
    HttpPost post = new HttpPost("/create");
    try {
        List<BasicNameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("track", MediaPackageElementParser.getAsXml(sourceTrack)));
        post.setEntity(new UrlEncodedFormEntity(params));
    } catch (Exception e) {
        throw new WaveformServiceException(e);
    }
    HttpResponse response = null;
    try {
        response = getResponse(post);
        if (response != null) {
            try {
                Job receipt = JobParser.parseJob(response.getEntity().getContent());
                logger.info("Create waveform image from {}", sourceTrack);
                return receipt;
            } catch (Exception e) {
                throw new WaveformServiceException("Unable to create waveform image from " + sourceTrack + " using a remote service", e);
            }
        }
    } finally {
        closeConnection(response);
    }
    throw new WaveformServiceException("Unable to create waveform image from " + sourceTrack + " using a remote service");
}
Also used : HttpPost(org.apache.http.client.methods.HttpPost) WaveformServiceException(org.opencastproject.waveform.api.WaveformServiceException) BasicNameValuePair(org.apache.http.message.BasicNameValuePair) ArrayList(java.util.ArrayList) HttpResponse(org.apache.http.HttpResponse) UrlEncodedFormEntity(org.apache.http.client.entity.UrlEncodedFormEntity) Job(org.opencastproject.job.api.Job) MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) WaveformServiceException(org.opencastproject.waveform.api.WaveformServiceException)

Example 3 with WaveformServiceException

use of org.opencastproject.waveform.api.WaveformServiceException in project opencast by opencast.

the class WaveformServiceImpl method process.

/**
 * {@inheritDoc}
 *
 * @see org.opencastproject.job.api.AbstractJobProducer#process(org.opencastproject.job.api.Job)
 */
@Override
protected String process(Job job) throws Exception {
    Operation op = null;
    String operation = job.getOperation();
    List<String> arguments = job.getArguments();
    try {
        op = Operation.valueOf(operation);
        switch(op) {
            case Waveform:
                Track track = (Track) MediaPackageElementParser.getFromXml(arguments.get(0));
                Attachment waveformMpe = extractWaveform(track);
                return MediaPackageElementParser.getAsXml(waveformMpe);
            default:
                throw new ServiceRegistryException("This service can't handle operations of type '" + op + "'");
        }
    } catch (IndexOutOfBoundsException e) {
        throw new ServiceRegistryException("This argument list for operation '" + op + "' does not meet expectations", e);
    } catch (MediaPackageException | WaveformServiceException e) {
        throw new ServiceRegistryException("Error handling operation '" + op + "'", e);
    }
}
Also used : MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) WaveformServiceException(org.opencastproject.waveform.api.WaveformServiceException) Attachment(org.opencastproject.mediapackage.Attachment) Track(org.opencastproject.mediapackage.Track) ServiceRegistryException(org.opencastproject.serviceregistry.api.ServiceRegistryException)

Example 4 with WaveformServiceException

use of org.opencastproject.waveform.api.WaveformServiceException in project opencast by opencast.

the class WaveformServiceEndpoint method createWaveformImage.

@POST
@Path("/create")
@Produces({ MediaType.APPLICATION_XML })
@RestQuery(name = "create", description = "Create a waveform image from the given track", returnDescription = "Media package attachment for the generated waveform.", restParameters = { @RestParameter(name = "track", type = RestParameter.Type.TEXT, description = "Track with at least one audio channel.", isRequired = true) }, reponses = { @RestResponse(description = "Waveform generation job successfully created.", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "The given track can't be parsed.", responseCode = HttpServletResponse.SC_BAD_REQUEST), @RestResponse(description = "Internal server error.", responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR) })
public Response createWaveformImage(@FormParam("track") String track) {
    try {
        MediaPackageElement sourceTrack = MediaPackageElementParser.getFromXml(track);
        if (!Track.TYPE.equals(sourceTrack.getElementType()))
            return Response.status(Response.Status.BAD_REQUEST).entity("Track element must be of type track").build();
        Job job = waveformService.createWaveformImage((Track) sourceTrack);
        return Response.ok().entity(new JaxbJob(job)).build();
    } catch (WaveformServiceException ex) {
        logger.error("Creating waveform job for track {} failed: {}", track, ExceptionUtils.getStackTrace(ex));
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    } catch (MediaPackageException ex) {
        return Response.status(Response.Status.BAD_REQUEST).entity("Track element parsing failure").build();
    }
}
Also used : MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) WaveformServiceException(org.opencastproject.waveform.api.WaveformServiceException) MediaPackageElement(org.opencastproject.mediapackage.MediaPackageElement) JaxbJob(org.opencastproject.job.api.JaxbJob) JaxbJob(org.opencastproject.job.api.JaxbJob) Job(org.opencastproject.job.api.Job) 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 WaveformServiceException

use of org.opencastproject.waveform.api.WaveformServiceException in project opencast by opencast.

the class WaveformWorkflowOperationHandler 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 waveform workflow operation for mediapackage {}", mediaPackage);
    String sourceFlavorProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(SOURCE_FLAVOR_PROPERTY));
    String sourceTagsProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(SOURCE_TAGS_PROPERTY));
    if (StringUtils.isEmpty(sourceFlavorProperty) && StringUtils.isEmpty(sourceTagsProperty)) {
        throw new WorkflowOperationException(String.format("Required property %s or %s not set", SOURCE_FLAVOR_PROPERTY, SOURCE_TAGS_PROPERTY));
    }
    String targetFlavorProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(TARGET_FLAVOR_PROPERTY));
    if (targetFlavorProperty == null) {
        throw new WorkflowOperationException(String.format("Required property %s not set", TARGET_FLAVOR_PROPERTY));
    }
    String targetTagsProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(TARGET_TAGS_PROPERTY));
    TrackSelector trackSelector = new TrackSelector();
    for (String flavor : asList(sourceFlavorProperty)) {
        trackSelector.addFlavor(flavor);
    }
    for (String tag : asList(sourceTagsProperty)) {
        trackSelector.addTag(tag);
    }
    Collection<Track> sourceTracks = trackSelector.select(mediaPackage, false);
    if (sourceTracks.isEmpty()) {
        logger.info("No tracks found in mediapackage {} with specified {} = {}", mediaPackage, SOURCE_FLAVOR_PROPERTY, sourceFlavorProperty);
        createResult(mediaPackage, WorkflowOperationResult.Action.SKIP);
    }
    List<Job> waveformJobs = new ArrayList<>(sourceTracks.size());
    for (Track sourceTrack : sourceTracks) {
        // Skip over track with no audio stream
        if (!sourceTrack.hasAudio()) {
            logger.info("Skipping waveform extraction of track {} since it has no audio", sourceTrack.getIdentifier());
            continue;
        }
        try {
            // generate waveform
            logger.info("Creating waveform extraction job for track '{}' in mediapackage '{}'", sourceTrack.getIdentifier(), mediaPackage);
            Job waveformJob = waveformService.createWaveformImage(sourceTrack);
            waveformJobs.add(waveformJob);
        } catch (MediaPackageException | WaveformServiceException e) {
            logger.error("Creating waveform extraction job for track '{}' in media package '{}' failed", sourceTrack.getIdentifier(), mediaPackage, e);
        }
    }
    logger.debug("Waiting for waveform jobs for media package {}", mediaPackage);
    if (!waitForStatus(waveformJobs.toArray(new Job[waveformJobs.size()])).isSuccess()) {
        cleanupWorkspace(waveformJobs);
        throw new WorkflowOperationException(String.format("Waveform extraction jobs for media package '%s' have not completed successfully", mediaPackage.getIdentifier()));
    }
    try {
        // copy waveform attachments into workspace and add them to the media package
        for (Job job : waveformJobs) {
            String jobPayload = job.getPayload();
            if (StringUtils.isEmpty(jobPayload)) {
                continue;
            }
            MediaPackageElement waveformMpe = null;
            try {
                waveformMpe = MediaPackageElementParser.getFromXml(jobPayload);
                URI newURI = workspace.moveTo(waveformMpe.getURI(), mediaPackage.getIdentifier().toString(), waveformMpe.getIdentifier(), "waveform.png");
                waveformMpe.setURI(newURI);
            } catch (MediaPackageException ex) {
                // unexpected job payload
                throw new WorkflowOperationException("Can't parse waveform attachment from job " + job.getId());
            } catch (NotFoundException ex) {
                throw new WorkflowOperationException("Waveform image file '" + waveformMpe.getURI() + "' not found", ex);
            } catch (IOException ex) {
                throw new WorkflowOperationException("Can't get workflow image file '" + waveformMpe.getURI() + "' from workspace");
            }
            // set the waveform attachment flavor and add it to the media package
            MediaPackageElementFlavor targetFlavor = MediaPackageElementFlavor.parseFlavor(targetFlavorProperty);
            if ("*".equals(targetFlavor.getType())) {
                targetFlavor = new MediaPackageElementFlavor(waveformMpe.getFlavor().getType(), targetFlavor.getSubtype());
            }
            if ("*".equals(targetFlavor.getSubtype())) {
                targetFlavor = new MediaPackageElementFlavor(targetFlavor.getType(), waveformMpe.getFlavor().getSubtype());
            }
            waveformMpe.setFlavor(targetFlavor);
            for (String tag : asList(targetTagsProperty)) {
                waveformMpe.addTag(tag);
            }
            mediaPackage.add(waveformMpe);
        }
    } finally {
        cleanupWorkspace(waveformJobs);
    }
    try {
        workspace.cleanup(mediaPackage.getIdentifier());
    } catch (IOException e) {
        throw new WorkflowOperationException(e);
    }
    logger.info("Waveform workflow operation for mediapackage {} completed", mediaPackage);
    return createResult(mediaPackage, WorkflowOperationResult.Action.CONTINUE);
}
Also used : MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) TrackSelector(org.opencastproject.mediapackage.selector.TrackSelector) ArrayList(java.util.ArrayList) NotFoundException(org.opencastproject.util.NotFoundException) IOException(java.io.IOException) URI(java.net.URI) MediaPackageElementFlavor(org.opencastproject.mediapackage.MediaPackageElementFlavor) WaveformServiceException(org.opencastproject.waveform.api.WaveformServiceException) MediaPackageElement(org.opencastproject.mediapackage.MediaPackageElement) MediaPackage(org.opencastproject.mediapackage.MediaPackage) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) Job(org.opencastproject.job.api.Job) Track(org.opencastproject.mediapackage.Track)

Aggregations

WaveformServiceException (org.opencastproject.waveform.api.WaveformServiceException)5 MediaPackageException (org.opencastproject.mediapackage.MediaPackageException)4 Job (org.opencastproject.job.api.Job)3 IOException (java.io.IOException)2 URI (java.net.URI)2 ArrayList (java.util.ArrayList)2 Attachment (org.opencastproject.mediapackage.Attachment)2 MediaPackageElement (org.opencastproject.mediapackage.MediaPackageElement)2 Track (org.opencastproject.mediapackage.Track)2 NotFoundException (org.opencastproject.util.NotFoundException)2 BufferedReader (java.io.BufferedReader)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 InputStreamReader (java.io.InputStreamReader)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 UrlEncodedFormEntity (org.apache.http.client.entity.UrlEncodedFormEntity)1