private List<String> parseJsonListOfString(String json) { if (json.isEmpty()) { return Lists.newArrayList(); } else { Gson gson = new Gson(); return gson.fromJson(json, new TypeToken<List<String>>() {}.getType()); } }
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); }