wseemann / FFmpegMediaMetadataRetriever

FFmpegMediaMetadataRetriever provides a unified interface for retrieving frame and meta data from an input media file.
1.72k stars 387 forks source link

METADATA_KEY_DURATION returns 0 for mp3 on android 6.0.1 but works on other versions #276

Open zkrige opened 1 year ago

zkrige commented 1 year ago
                try {
                    FFmpegMediaMetadataRetriever metadataRetriever = new FFmpegMediaMetadataRetriever();
                    ZipMediaDataSource zipMediaDataSource = new ZipMediaDataSource(zipFile, zipEntry);
                    metadataRetriever.setDataSource(zipMediaDataSource);
                    String duration;
                    try {
                        duration = metadataRetriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION);
                        long durationMs = Long.parseLong(duration);
                        chapter.duration = durationFormat(durationMs);
                    } catch (Exception e) {
                        chapter.duration = "n/a";
                    }
                    metadataRetriever.release();
                } catch (IOException e) {
                    chapter.duration = "n/a";
                }

on android 6.0.1 im getting "0" as duration, but on other devices I get the actual duration of the mp3.

wseemann commented 1 year ago

Can you post ZipMediaDataSource? The issue is likely due to come API specific behavior in whatever that class is doing.

zkrige commented 1 year ago

Turns out im getting 0 duration on all android platforms. I managed to get it working with MediaMetadataRetriever, so I dont think its ZipMediaDatasource that is the problem - also ZipMediaDatasource works fine with MediaMetadataRetriever

@RequiresApi(api = Build.VERSION_CODES.M)
public class InputStreamDataSource extends MediaDataSource {
    protected InputStream inputStream;
    protected ZipFile zipFile;
    protected ZipEntry zipEntry;
    private long currentPosition = 0;

    @Override
    public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
        if (currentPosition > position) {
            Timber.v("Resetting stream: " + zipEntry.getName());
            reset();
        }
        if (position > 0) {
            long toSkip = position - currentPosition;
            long skipped = inputStream.skip(toSkip);
            while (skipped < toSkip) {
                skipped = skipped + inputStream.skip(toSkip - skipped);
            }
        }
        int bytesRead = inputStream.read(buffer, offset, size);
        if (size != bytesRead) {
            Timber.d("Requested: " + size + " but only got " + bytesRead);
        }
        if (position >= 0) {
            currentPosition = currentPosition + position + bytesRead;
            Timber.v("Current position for " + zipEntry.getName() + ":" + currentPosition);
        }
        return bytesRead;
    }

    private void reset() throws IOException {
        inputStream.close();
        inputStream = zipFile.getInputStream(zipEntry);
        currentPosition = 0;
    }

    @Override
    public long getSize() throws IOException {
        return inputStream.available();
    }

    @Override
    public void close() throws IOException {
        if (inputStream != null) {
            inputStream.close();
            inputStream = null;
        }

    }
}

@RequiresApi(api = Build.VERSION_CODES.M)
public class ZipMediaDataSource extends InputStreamDataSource {

    public ZipMediaDataSource(ZipFile file, ZipEntry zipEntry) throws IOException {
        this.zipFile = file;
        this.zipEntry = zipEntry;
        inputStream = file.getInputStream(zipEntry);
    }
}