a-schild / jave2

The JAVE (Java Audio Video Encoder) library is Java wrapper on the ffmpeg project
GNU General Public License v3.0
1.2k stars 245 forks source link

when lots of videos to concat . EncoderProgressListernr get a NPE Exception #178

Open naffan2014 opened 2 years ago

naffan2014 commented 2 years ago

jave 3.2.0

First,i have add lots of videos in encode()

// filePathList contains lots of videos absolute path;

for (String o : filePathList) {
            File sourceTmp = new File(o);
            src.add(new MultimediaObject(sourceTmp));
        }
        encoder.encode(src, target, attrs, monitoringConcatListener);

As we can see above,i want to get more informations from MonitoringConcatListener. this is my code

@Slf4j
public class MonitoringConcatListener implements EncoderProgressListener {

    @Override
    public void sourceInfo(MultimediaInfo info) {
        AudioInfo ai = info.getAudio();
        VideoInfo vi = info.getVideo();
        Long duration = info.getDuration();
        Map<String,String> metaMap = info.getMetadata();
        LOGGER.info("ai:{},vi:{},duration:{},meta:{}",ai,vi,duration,metaMap);
    }

    @Override
    public void progress(int permil) {
        if(permil ==0 ){
            LOGGER.info("concat start");
        } else if(permil == 500){
            LOGGER.info("50%");
        }else if(permil == 1000){
            LOGGER.info("concat end");
        }
    }

    @Override
    public void message(String message) {
        LOGGER.info("concat waring:",message);
    }
}

At the end, when i ran my code , jvm throw a null pointer exception. After my digging into your code.i found that in Encoder.java lines 551:

try {

      MultimediaInfo info = null;
      /*
    .....
       */
     // you only care about one  video. 
      if (multimediaObjects.size() == 1
          && (!multimediaObjects.get(0).isURL() || !multimediaObjects.get(0).isReadURLOnce())) {
        info = multimediaObjects.get(0).getInfo();
      }

      Float offsetAttribute = attributes.getOffset().orElse(null);
      Float durationAttribute = attributes.getDuration().orElse(null);
      if (durationAttribute != null) {
        duration = (long) Math.round((durationAttribute * 1000L));
      } else {
        if (info != null) {
          duration = info.getDuration();
          if (offsetAttribute != null) {
            duration -= (long) Math.round((offsetAttribute * 1000L));
          }
        }
      }

      // when there are more videos, info is null.
      if (listener != null) {
        listener.sourceInfo(info);
      }

i don't understand why you miss List logic. if it is a bug? or my fault?

a-schild commented 2 years ago

Hello @naffan2014 , thanks for reporting this. You are welcome to enhance that code part. And in future, please post the full stack trace when you got any exception

jhsea3do commented 2 years ago

this problem caused by ffmpeg version 4.4.x, since the jave version is above 3.2.0.

to reproduce this issue, please run below junit code

@Test
    public void testMergeFiles() {
        VideoProcessor vps = new VideoProcessor();
        String workdir = "testMergeFiles";
        String sample  = "desktop01.flv";
        String output  = "desktop01sum.flv";
        String baseDir = System.getProperty("java.io.tmpdir") + File.separator + workdir;
        List<String> files = new LinkedList<>();
        files.add(baseDir + "/" + sample);
        List<File> videos = files
                .stream()
                .map(File::new)
                .collect(Collectors.toList());
        File mergedFile = new File(baseDir + File.separator + output);
        try {
            vps.catClipsTogether(videos, mergedFile, new EchoingProgressListener("Test Merge Files"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (EncoderException e) {
            e.printStackTrace();
        }
    }

merge files task will failed, and get this exception, please notice the command line of the second DEBUG message.

21:40:39,296 [DEBUG ] ProcessWrapper.execute(ProcessWrapper.java:99) - About to execute C:\Users\xxx\workspace\temp\jave\ffmpeg-amd64-3.2.0.exe -f concat -safe 0 -i C:\Users\xxx\workspace\temp\testMergeFiles\desktop01sum.flv.merge.txt -vcodec copy -movflags faststart -an -y C:\Users\xxx\workspace\temp\testMergeFiles\desktop01sum.flv -hide_banner
21:40:42,593 [DEBUG ] ProcessWrapper.execute(ProcessWrapper.java:99) - About to execute C:\Users\xxx\workspace\temp\jave\ffmpeg-amd64-3.2.0.exe -i C:\Users\xxx\workspace\temp\testMergeFiles\desktop01sum.flv.merge.txt -hide_banner
....
ws.schild.jave.InputFormatException: Invalid data found when processing input
    at ws.schild.jave.MultimediaObject.parseMultimediaInfo(MultimediaObject.java:217)
    at ws.schild.jave.MultimediaObject.getInfo(MultimediaObject.java:165)
    at ws.schild.jave.Encoder.encode(Encoder.java:534)
    at ws.schild.jave.Encoder.encode(Encoder.java:351)
    at ws.schild.jave.VideoProcessor.catClipsTogether(VideoProcessor.java:83)

because the ffmpeg 4.4.x did not accept arguments "-i merge.txt",
here is the command line output difference between ffmpeg v4.4.1 and v4.2.2

$ ./ffmpeg-amd64-4.2.2-static -i ../feature1/desktop01sum.flv.merge.txt -hide_banner
Input #0, tty, from '../feature1/desktop01sum.flv.merge.txt':
  Duration: 00:00:00.04, bitrate: 23 kb/s
    Stream #0:0: Video: ansi, pal8, 640x400, 25 fps, 25 tbr, 25 tbn, 25 tbc
At least one output file must be specified

$ ./ffmpeg-amd64-4.4.1-static -i ../feature1/desktop01sum.flv.merge.txt -hide_banner
../feature1/desktop01sum.flv.merge.txt: Invalid data found when processing input
jhsea3do commented 2 years ago

I have submit the patch for this issue. #209

otherwise, we may need downgrade the jave-nativebin-xxx version to 3.1.1 to invoid this issue.

        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-core</artifactId>
            <version>3.2.0</version>
        </dependency>

        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-nativebin-linux64</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-nativebin-win64</artifactId>
            <version>3.1.1</version>
        </dependency>