Esempio n. 1
0
  public VideoConversion createVideo(final Face face) {
    final List<PhotoInfo> photoInfos = photoManager.getPhotosForFace(face);
    final List<File> photoFiles = Lists.newArrayList();
    for (PhotoInfo info : photoInfos) photoFiles.add(info.getPhotoFile());
    final File progressFile = new File(getTmpVideoDir(), "progress");
    final Observable<File> conversionObservable =
        Observable.defer(
                new Func0<Observable<File>>() {
                  @Override
                  public Observable<File> call() {
                    // rename photos to img0000.jpg + process photos
                    Collections.sort(photoFiles);
                    int idx = 0;
                    for (File oldFile : photoFiles) {
                      ++idx;
                      try {
                        // process image
                        Bitmap originalImage = BitmapFactory.decodeFile(oldFile.getAbsolutePath());
                        Bitmap processedImage = photoProcessor.findFaceAndCrop(originalImage);

                        // store image
                        final File newFile =
                            new File(getTmpVideoDir(), "img" + String.format("%03d", idx) + ".jpg");
                        if (!newFile.createNewFile())
                          Timber.e("failed to create file " + newFile.getAbsolutePath());
                        processedImage.compress(
                            Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(newFile));
                      } catch (IOException e) {
                        Timber.d(e, "failed to copy + process file");
                        return Observable.error(e);
                      }
                    }

                    // create conversion command
                    final String photoFileNameTemplate =
                        getTmpVideoDir().getAbsolutePath() + "/img%03d.jpg";
                    final String videoFileName = VIDEO_DATE_FORMAT.format(new Date()) + ".mp4";
                    final File videoFile = new File(getExternalFaceVideoDir(face), videoFileName);

                    final String command =
                        String.format(
                            "-progress %s -framerate 1/%d -i %s -c:v libx264 -r %d -pix_fmt yuv420p %s",
                            progressFile.getAbsolutePath(),
                            IMAGE_LENGTH_IN_SECONDS,
                            photoFileNameTemplate,
                            FRAMERATE,
                            videoFile.getAbsolutePath());

                    Timber.d("executing ffmpeg: " + command);

                    // start command
                    return Observable.create(
                        new Observable.OnSubscribe<File>() {
                          @Override
                          public void call(final Subscriber<? super File> subscriber) {
                            try {
                              fFmpeg.execute(
                                  command,
                                  new FFmpegExecuteResponseHandler() {
                                    @Override
                                    public void onSuccess(String s) {
                                      Timber.d("video conversion success: " + s);
                                      if (subscriber.isUnsubscribed()) return;
                                      subscriber.onNext(videoFile);
                                      subscriber.onCompleted();
                                    }

                                    @Override
                                    public void onProgress(String s) {
                                      Timber.d("video conversion progress: " + s);
                                    }

                                    @Override
                                    public void onFailure(String s) {
                                      Timber.d("video conversion error: " + s);
                                      subscriber.onError(new IllegalStateException(s));
                                    }

                                    @Override
                                    public void onStart() {
                                      Timber.d("video conversion started");
                                    }

                                    @Override
                                    public void onFinish() {
                                      Timber.d("video conversion finished");
                                    }
                                  });
                            } catch (FFmpegCommandAlreadyRunningException e) {
                              Timber.e(e, "failed to start video conversion");
                              if (subscriber.isUnsubscribed()) return;
                              subscriber.onError(e);
                            }
                          }
                        });
                  }
                })
            .finallyDo(
                new Action0() {
                  @Override
                  public void call() {
                    // cleanup
                    ioUtils.delete(getTmpVideoDir());
                  }
                });
    return new VideoConversion(progressFile, photoFiles.size(), conversionObservable);
  }