Tässä Java-sovelluksessa yritän muuntaa videon pieniksi leikkeiksi.

Tässä on toteutusluokka samalle

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; } } 

Koko ratkaisu on käytettävissä osoitteessa Github . Käytän itse asiassa CompletableFuture ja suoritan FFMPEG-komennon luomalla Java-prosessin. Se vie liian paljon aikaa. 40 minuutin videolle kestää yli 49 minuuttia 64-keskusyksiköllä. Yritän pienentää ytimen kokoa 8: een tai mihin tahansa sekä parantaa sen suorituskykyä, koska tällaista suorituskykyä ei voida hyväksyä minkäänlaisissa sovelluksissa.

22.1.2017 päivitys
Yksi päivitys, olen muuttanut FFMPEG-komentoa luoda leikkeitä ja päivittänyt FFMPEG 3: een, mutta parannusta ei ole.

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

Kommentit

  • Lähetin joitain esimerkkejä JavaCV: llä en kokeillut ’ en kokeillut pitkää videovideota, mutta lyhyitä videoita (ts. 5 minuuttia) käsittelyaika on noin 1 minuutti.

Vastaus

Se on luonnollinen videorajoitus koodaus: Nykyaikaisissa koneissa 1 minuutti 720p-videota koodataan noin minuutissa.

Voit säästää paljon aikaa, jos et tarvitse uudelleenkoodausta. (eli koodekin tai videon koon muuttaminen) käyttämällä -codec copy ffmpeg-vaihtoehtoa.

Sanoit myös, että sinulla on 64 ydintä, mutta koodissasi käytetään vain yhtä säiettä koodaukseen. Käytä -threads 0 antaa ffmpegin valita itse.

Jos sinun on suoritettava tämä Java-ohjelmassa, anna Jaffree mahdollisuus (olen kirjoittaja).

Kommentit

  • Jos kirjoitit Jaffree, ilmoita niin nimenomaisesti .
  • github.com/bramp/ffmpeg-cli-wrapper saattaa olla parempi ratkaisu sinulle.
  • Aloitin Jaffree-ohjelman juuri useiden ffmpeg-cli-wrapper-ongelmien takia.

Vastaa

Tiedän, että tämä on vanha kysymys, mutta mielestäni tästä voi olla hyötyä Java-kehittäjille.

On mukava kirjasto nimeltä JavaCV, tämä live on kääre useille C- ja C ++ -kirjastoille, kuten FFmpeg.

Tämä on yksinkertainen esimerkki muuntimen käyttöönotosta:

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(); } } 

Tämä perustoteutus näyttää videon muuntamisen FFmpeg-paketti tai a JavaCV-kehys .

Kommentit

  • Tervetuloa Code Review -ohjelmaan. Olet esittänyt vaihtoehtoisen ratkaisun, mutta ’ ei ole tarkistanut koodia. Selitä perustelut (miten ratkaisusi toimii ja miksi se on alkuperäistä parempi), jotta kirjailija ja muut lukijat voivat oppia ajatusprosessistasi.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *