I dette java-programmet prøver jeg å konvertere en video til små klipp.

Her er implementeringsklassen for samme

package ffmpeg.clip.process; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Paths; import java.time.Duration; import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import ffmpeg.clip.utils.VideoConstant; import ffmpeg.clip.utils.VideoUtils; /* * @author Nitishkumar Singh * @Description: class will use ffmpeg to break an source video into clips */ public class VideoToClip { /* * Prevent from creating instance */ private VideoToClip() { } /** * Get Video Duration is milliseconds * * @Exception IOException - File does not exist VideoException- Video File have data issues */ static LocalTime getDuration(String sourceVideoFile) throws Exception { if (!Paths.get(sourceVideoFile).toFile().exists()) throw new Exception("File does not exist!!"); Process proc = new ProcessBuilder(VideoConstant.SHELL, VideoConstant.SHELL_COMMAND_STRING_ARGUMENT, String.format(VideoConstant.DURATION_COMMAND, sourceVideoFile)).start(); boolean errorOccured = (new BufferedReader(new InputStreamReader(proc.getErrorStream())).lines() .count() > VideoConstant.ZERO); String durationInSeconds = new BufferedReader(new InputStreamReader(proc.getInputStream())).lines() .collect(Collectors.joining(System.lineSeparator())); proc.destroy(); if (errorOccured || (durationInSeconds.length() == VideoConstant.ZERO)) throw new Exception("Video File have some issues!"); else return VideoUtils.parseHourMinuteSecondMillisecondFormat(durationInSeconds); } /** * Create Clips for Video Using Start and End Second * * @Exception IOException - Clip Creation Process Failed InterruptedException - Clip Creation task get"s failed */ static String toClipProcess(String sourceVideo, String outputDirectory, LocalTime start, LocalTime end, String fileExtension) throws IOException, InterruptedException, ExecutionException { String clipName = String.format(VideoConstant.CLIP_FILE_NAME, VideoUtils.getHourMinuteSecondMillisecondFormat(start), VideoUtils.getHourMinuteSecondMillisecondFormat(end), fileExtension); String command = String.format(VideoConstant.FFMPEG_OUTPUT_COMMAND, sourceVideo, VideoUtils.getHourMinuteSecondMillisecondFormat(start), VideoUtils.getHourMinuteSecondMillisecondFormat(end.minus(start.toNanoOfDay(), ChronoUnit.NANOS)), outputDirectory, clipName); LocalTime startTime = LocalTime.now(); System.out.println("Clip Name: " + clipName); System.out.println("FFMPEG Process Execution Started"); CompletableFuture<Process> completableFuture = CompletableFuture.supplyAsync(() -> { try { return executeProcess(command); } catch (InterruptedException | IOException ex) { throw new RuntimeException(ex); } }); completableFuture.get(); // remove LocalTime endTime = LocalTime.now(); System.out.println("Clip Name: " + clipName); System.out.println("FFMPEG Process Execution Finished"); System.out.println("Duration: " + Duration.between(startTime, endTime).toMillis() / 1000); return clipName; } /** * Create and Execute Process for each command */ static Process executeProcess(String command) throws InterruptedException, IOException { Process clipProcess = Runtime.getRuntime().exec(command); clipProcess.waitFor(); return clipProcess; } } 

Hele løsningen er tilgjengelig på Github . Jeg bruker faktisk CompletableFuture og kjører FFMPEG-kommando ved å lage Java Process. Tiden det tar er for mye. For en 40-minutters video tar det mer enn 49 minutter på en 64 CPU-maskin. Jeg prøver å redusere kjernestørrelsen til 8 eller noe, samt forbedre ytelsen, ettersom denne typen ytelse ikke vil være akseptabel for alle slags applikasjoner.

22. januar 2017 oppdatering
Én oppdatering, jeg har endret FFMPEG-kommandoen for å lage klipp og oppdatert til FFMPEG 3, men det er ingen forbedring.

ffmpeg -y -i INPUT_FILE_PATH -ss TIME_STAMP -t DURATION_TO_CLIP OUTPUT_FILE_PATH

Kommentarer

  • Jeg la ut noen eksempler ved bruk av JavaCV. Jeg gjorde ikke ‘ t prøvde med en lang videovideo, men for korte videoer (dvs. 5 minutter) er behandlingstiden omtrent 1 minutt.

Svar

Det er en naturlig begrensning på video koding. På moderne maskiner blir 1 minutt 720p video kodet omtrent på 1 minutt.

Du kan spare mye tid hvis du ikke trenger omkoding (dvs. endre kodek eller videostørrelse) ved å bruke -codec copy ffmpeg-alternativet.

Du sa også at du har 64 kjerner, men koden din bruker bare en tråd for koding. Bruk -threads 0 for å la ffmpeg velge selv.

Også, hvis du trenger å utføre dette i Java – gi Jaffree en sjanse (jeg er en forfatter).

Kommentarer

  • Hvis du skrev Jaffree, vær så snill å si så eksplisitt .
  • github.com/bramp/ffmpeg-cli-wrapper kan være en bedre løsning for deg.
  • Jeg startet Jaffree nøyaktig på grunn av flere problemer med ffmpeg-cli-wrapper.

Svar

Jeg vet at dette er et gammelt spørsmål, men jeg tror dette kan være nyttig for Java-utviklere.

Det er et fint bibliotek som heter JavaCV. Dette er en innpakning for flere C- og C ++ -biblioteker som FFmpeg.

Dette er et enkelt eksempel på hvordan du implementerer en omformer:

import org.bytedeco.javacpp.avcodec; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class PacketRecorderTest { private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd__hhmmSSS"); private static final int RECORD_LENGTH = 5000; private static final boolean AUDIO_ENABLED = false; public static void main(String[] args) throws FrameRecorder.Exception, FrameGrabber.Exception { String inputFile = "/home/usr/videos/VIDEO_FILE_NAME.mp4"; // Decodes-encodes String outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_frameRecord.mp4"; PacketRecorderTest.frameRecord(inputFile, outputFile); // copies codec (no need to re-encode) outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_packetRecord.mp4"; PacketRecorderTest.packetRecord(inputFile, outputFile); } public static void frameRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception { int audioChannel = AUDIO_ENABLED ? 1 : 0; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); grabber.start(); recorder.start(); Frame frame; long t1 = System.currentTimeMillis(); while ((frame = grabber.grabFrame(AUDIO_ENABLED, true, true, false)) != null) { recorder.record(frame); if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) { break; } } recorder.stop(); grabber.stop(); } public static void packetRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception { int audioChannel = AUDIO_ENABLED ? 1 : 0; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); grabber.start(); recorder.start(grabber.getFormatContext()); avcodec.AVPacket packet; long t1 = System.currentTimeMillis(); while ((packet = grabber.grabPacket()) != null) { recorder.recordPacket(packet); if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) { break; } } recorder.stop(); grabber.stop(); } } 

Denne grunnleggende implementeringen viser hvordan du konverterer en video ved hjelp av en FFmpeg-pakke eller en JavaCV-ramme .

Kommentarer

  • Velkommen til Code Review. Du har presentert en alternativ løsning, men har ikke ‘ t gjennomgått koden. Vennligst forklar resonnementet ditt (hvordan løsningen din fungerer og hvorfor den er bedre enn originalen) slik at forfatteren og andre lesere kan lære av tankeprosessen din.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *