mp4文件复制再写入后无法播放

mp4 file doesn't get played after being copied and written again

当我尝试使用 Mp4Parse 的一种方法将 mp4 从一个文件夹复制到另一个文件夹时,一切正常。当我尝试利用其中一种方法的输出来创建新对象,然后使用它们将文件写入另一个文件夹时,事情并没有完全解决。下面是我使用的代码:

我用这个class提取元数据并用相应的数据创建videoFile对象(评论是我用来确保它正常工作的剩余代码)

编辑 1: 经过一些测试后,我发现出于某种原因,即使 Mp4Parse.NoChunkMethod 中的 temp 不是空的或空的(我通过打印其所有内容来检查)方法 returns 的字节数组只有 0

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;

import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.mp4.MP4Parser;
import org.apache.tika.sax.BodyContentHandler;

import org.xml.sax.SAXException;

public class Mp4Parse {

    static int chunk_size = 512;


    public ArrayList<videoFile> chunkingMethod(String arg) throws IOException,SAXException, TikaException {

        String sourcefilePath = arg;
//      String outputfilePath = "C:\Users\ilias-vasilis\Desktop\test1\video0.mp4";


        //Next 2 lines exist only to give me the size of the file in bytes
        Path path = Paths.get(sourcefilePath);
        long fileSize = Files.size(path);

        int chunk_num = (int)fileSize/chunk_size;
        byte[] temp = new byte[(int)fileSize];

        //data structure to store the chunks in
        ArrayList<byte[]> chunks = new ArrayList<>(chunk_num);

        //videoFile data structure
        ArrayList<videoFile> video = new ArrayList<>(chunk_num);

        //detecting the file type
        BodyContentHandler handler = new BodyContentHandler();
        Metadata metadata = new Metadata();
        FileInputStream inputstream = new FileInputStream(sourcefilePath);
        ParseContext pcontext = new ParseContext();

        //Html parser
        MP4Parser MP4Parser = new MP4Parser();
        MP4Parser.parse(inputstream, handler, metadata,pcontext);
        System.out.println("Contents of the document:  :" + handler.toString());
        System.out.println("Metadata of the document:");
        String[] metadataNames = metadata.names();

        for(String name : metadataNames) {
            System.out.println(name + ": " + metadata.get(name));
        }
        inputstream.close();

        FileInputStream myInputStream = new FileInputStream(new File(sourcefilePath));
//      FileOutputStream outputStream = new FileOutputStream(new File(outputfilePath));
        while(myInputStream.available() != 0) {
            myInputStream.read(temp);
        }

        for(int j = 0; j < chunk_num; j++){
            chunks.add(new byte[512]);
            //Copy the elements of temp in chunks of "chunk_size"
            System.arraycopy(temp, j * chunk_size, chunks.get(j), 0, chunk_size);
        }


        int i = 0;
        //After splitting the mp4 in chunks make the videoFile objects
        for(byte[] b:chunks) {
//          outputStream.write(b);
            video.add(new videoFile(b,null));
            i++;
        }
        myInputStream.close();
        return video;
//      outputStream.close();
   }


//##########################################################################################################################

    //Simple transfer without splitting
   public videoFile NoChunkMethod(String arg) throws IOException,SAXException, TikaException{
       String sourcefilePath = arg;
//      String outputfilePath = "C:\Users\ilias-vasilis\Desktop\Distributed-Systems-Project-main\Files\test\video1.mp4";


       //Next 2 lines exist only to give me the size of the file in bytes
       Path path = Paths.get(sourcefilePath);
       long fileSize = Files.size(path);
       byte[] temp = new byte[(int)fileSize];


       //detecting the file type
       BodyContentHandler handler = new BodyContentHandler();
       Metadata metadata = new Metadata();
       FileInputStream inputstream = new FileInputStream(sourcefilePath);
       ParseContext pcontext = new ParseContext();

       //Html parser
       MP4Parser MP4Parser = new MP4Parser();
       MP4Parser.parse(inputstream, handler, metadata,pcontext);
       System.out.println("Contents of the document:  :" + handler.toString());
       System.out.println("Metadata of the document:");
       String[] metadataNames = metadata.names();

       for(String name : metadataNames) {
           System.out.println(name + ": " + metadata.get(name));
       }
       inputstream.close();

       FileInputStream myInputStream = new FileInputStream(new File(sourcefilePath));
//       FileOutputStream outputStream = new FileOutputStream(new File(outputfilePath));

       int bytesRead;
       while(myInputStream.available() != 0) {
           bytesRead = myInputStream.read(temp);
//           outputStream.write(temp, 0, bytesRead);
       }

       myInputStream.close();
       videoFile video = new videoFile(temp, null);
       return video;
   }
}

这几乎就是我想要存储视频的class。稍后我将开始为元数据赋值

import java.io.Serializable;
import java.util.*;

public class videoFile implements Serializable {

    private static final long serialVersionUID = 1L;

    String videoName; //Name of the video (video title)
    String channelName; //Name of the channel it was posted on
    String dateCreated; //The date it was uploaded or the date it is created (taken from metadata if possible)
    String length; //Length of the video in seconds (Maybe declare it as int)
    String framerate; //Self explanatory (maybe declare as int)
    String frameWidth; //Width of the viewing window (maybe declare as int)
    String frameHeight; //Same as above but with height
    ArrayList<String> associatedHashtags; //Hashtags the publisher tagged the video with
    byte[] videoFileChunk; //Byte array, possibly just used to store the entire vid or a single chunk to send over the Internet
    int serialNumber = 0;

    public videoFile(){
        videoName = null;
        channelName = null;
        dateCreated = null;
        length = null;
        framerate = null;
        frameWidth = null;
        frameHeight = null;
        associatedHashtags = null;
        videoFileChunk = null;
        serialNumber++;
    }

    public videoFile(byte[] chunk, String channelName){
        videoName = null;
        this.channelName = channelName;
        dateCreated = null;
        length = null;
        framerate = null;
        frameWidth = null;
        frameHeight = null;
        associatedHashtags = null;
        videoFileChunk = new byte[chunk.length];
        System.arraycopy(videoFileChunk, 0, chunk, 0, chunk.length);
        serialNumber++;
    }

    public videoFile(String vname, String chname, String creationdate, String length,
                     String framerate, String frameWidth, String frameHeight,
                     ArrayList<String> hashtags, byte[] chunk)
    {
        videoName = vname;
        channelName = chname;
        dateCreated = creationdate;
        this.length = length;
        this.frameHeight = framerate;
        this.frameWidth = frameWidth;
        this.frameHeight = frameHeight;
        associatedHashtags = new ArrayList<>(hashtags);
        videoFileChunk = new byte[chunk.length];
        System.arraycopy(videoFileChunk, 0, chunk, 0, chunk.length);
        serialNumber++;
    }

    public videoFile(videoFile vidFile){
        videoFileChunk = new byte[vidFile.videoFileChunk.length];
        System.arraycopy(videoFileChunk, 0, vidFile.videoFileChunk,
                0, vidFile.videoFileChunk.length);

        this.channelName = vidFile.channelName;
        videoName = null;
        dateCreated = null;
        length = null;
        framerate = null;
        frameWidth = null;
        frameHeight = null;
        associatedHashtags = null;
    }

    public videoFile(videoFile vidFile, String channelName){

        this.channelName = channelName;
        videoFileChunk = new byte[vidFile.videoFileChunk.length];
        System.arraycopy(videoFileChunk, 0, vidFile.videoFileChunk,
                0, vidFile.videoFileChunk.length);

        videoName = null;
        dateCreated = null;
        length = null;
        framerate = null;
        frameWidth = null;
        frameHeight = null;
        associatedHashtags = null;
    }

    public byte[] getVideoFileChunk(){
        return videoFileChunk;
    }

}

这是我在 Mp4Parse 之外用于测试的代码

String path = "Files/ConsumerFiles/video1.mp4";
Mp4Parse mp4 = new Mp4Parse();
videoFile temp = new videoFile(mp4.NoChunkMethod(path));
videoFile video = new videoFile(temp, channelName);

FileOutputStream fop = new FileOutputStream("Files/test/video1.mp4");
fop.write(video.getVideoFileChunk());
fop.close();

此代码成功复制了正确大小的 mp4 文件,但视频无法播放,Windows 通知我它可能已损坏。

vidFile 的构造函数有问题。基本上我反向使用 Arrays.arraycopy 参数(我从空数组复制到完整数组)