2013-02-27 37 views
8

Tôi đang cố trích xuất tất cả các khung hình từ video.
Bằng mã sau tôi muốn tìm nạp 30 khung hình đầu tiên của video, nhưng tôi chỉ nhận được khung hình đầu tiên 30 lần.Trích xuất bitmap từ video trong android

private ArrayList<Bitmap> getFrames(String path) { 
    try { 
     ArrayList<Bitmap> bArray = new ArrayList<Bitmap>(); 
     bArray.clear(); 
     MediaMetadataRetriever mRetriever = new MediaMetadataRetriever(); 
     mRetriever.setDataSource("/sdcard/myvideo.mp4");      

     for (int i = 0; i < 30; i++) { 
      bArray.add(mRetriever.getFrameAtTime(1000*i, 
         MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); 
     } 
     return bArray; 
    } catch (Exception e) { return null; } 
} 

Bây giờ, làm cách nào để có được tất cả các khung hình từ video?

+0

Thời gian cho 'getFrameAtTime' là một phần triệu giây, do đó, đối với video 30 fps, sẽ có khoảng 33333 micro giây giữa mỗi khung. Khung cuối cùng mà mã của bạn cố gắng đọc là 30000 micro giây - tức là bạn thậm chí sẽ không chuyển sang khung thứ hai (tùy thuộc vào tốc độ khung hình của bạn). Một điều nữa là 'OPTION_CLOSEST_SYNC' truy xuất _keyframe_ gần nhất với thời gian bạn chỉ định. Thường có ít khung hình chính hơn tổng số khung hình trong video nén. – Michael

+0

Xin chào @Michael, Video của tôi với 30 khung hình/giây. Và bây giờ tôi đang sử dụng sau mã cho bitmap trích .... for (int i = 0; i <10; i ++) { \t \t \t \t bArray.add (mRetriever.getFrameAtTime (33333 * i, \t \t \t \t \t \t MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); \t \t \t} nhưng không có gì thay đổi .. ở đây tôi chỉ có khung đầu tiên trong bitmap .. –

+1

Như tôi đã viết trong bình luận đầu tiên, bạn sẽ lấy keyframe gần nhất với thời gian đã cho khi bạn sử dụng 'OPTION_CLOSEST_SYNC'. Không chắc video có chứa 10 khung hình trở lên cho mỗi khung hình chính. Sử dụng 'OPTION_CLOSEST' nếu bạn muốn nhận bất kỳ loại khung hình nào thay vì chỉ các khung hình chính. – Michael

Trả lời

2

Hỗ trợ video trong SDK Android bị giới hạn và việc trích xuất khung hình cho video được mã hóa H264 chỉ có thể thực hiện đối với các khung chính. Để trích xuất một khung tùy ý, bạn sẽ cần phải sử dụng thư viện như FFmpegMediaMetadataRetriever sử dụng mã gốc để trích xuất dữ liệu từ video. Nó rất nhanh, đi kèm với các tệp nhị phân được biên dịch sẵn (cho ARM và x86), do đó bạn không cần phải nghiên cứu về C++ và makefiles, được cấp phép theo Apache 2.0 và nó đi kèm với một ứng dụng Android demo.

Ngoài ra còn có một thư viện Java thuần túy, JCodec nhưng nó chậm hơn và khi tôi sử dụng nó năm ngoái, màu sắc của khung được trích xuất bị méo.

+0

Tôi đã thử JCodec, nhưng tôi không thể nhận được bất cứ điều gì ngoài khung hình chính từ một chuyển động chậm 240fps mp4. Tôi đã kết thúc bằng cách sử dụng các ràng buộc Java của opencv, lớp VideoCapture. Tôi tin rằng nó đang sử dụng ffmpeg dưới bìa. Tôi đã có thể nhận được tất cả các khung hình, và dấu thời gian của mỗi fames và tổng số khung hình của video là tốt. CẢNH BÁO - đây là java sdk, tôi chưa thử opencv mới nhất cho android. – medloh

0

getFrameTìm dữ liệu theo mili giây nhưng bạn đang tăng 0,001 miligiây trong vòng lặp.

for(int i=1000000;i<millis*1000;i+=1000000) // for incrementing 1s use 1000 
    { 
     bArray.add(mRetriever.getFrameAtTime(i, 
         MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); 
    } 

thay đổi nó như trên. Trên đây là mẫu để tạo ra những gì bạn muốn. Tôi cũng đã trả lời nó here

Các vấn đề liên quan