Chuyển đổi hàng ngàn .png thành hoạt hình .gif, `convert` sử dụng quá nhiều bộ nhớ


29

Nhiều câu hỏi hỏi làm thế nào để tạo một gif hoạt hình từ một tập hợp các hình ảnh png gợi ý sử dụng một biến thể của convertlệnh ImageMagick :

convert -delay 2 -loop 0 *.png animated.gif

Tuy nhiên, tôi có một vài nghìn hình ảnh và do đó convertsử dụng hết bộ nhớ, trao đổi và sau đó gặp sự cố. Phần mềm thay thế nào tồn tại, có ý thức bộ nhớ hơn? Tôi có thể sử dụng định dạng mở khác nếu .gifkhông được hỗ trợ và tôi thích công cụ CLI hơn.


1
Làm thế nào về việc chia các tệp * .png thành các phần có thể quản lý? Giả sử tất cả tên tệp bắt đầu bằng một chữ số, sau đó convert -delay 2 -loop 0 0*.png animated.gifsẽ chỉ chuyển đổi các tệp bắt đầu bằng '0'. Và như vậy.
Jos

2
Vậy mỗi .png theo thứ tự 1 Mb? Trong trường hợp đó, tất cả những gì tôi có thể nghĩ đến là trước tiên chuyển đổi các tệp .png sang độ phân giải hoặc độ sâu màu thấp hơn, để làm cho chúng nhỏ hơn.
Jos

10
Bạn nói rằng bạn có thể sử dụng một định dạng mở khác. Dường như với tôi rằng gif không chính xác là định dạng tốt nhất cho hàng ngàn khung hình. Thay vào đó, bạn đã xem xét việc mã hóa video bằng Ogg Theora chưa?
rekado

1
Có lẽ hãy xem gifsicle , nếu bạn thực sự muốn sử dụng GIF? (Mặc dù, như những người khác đã nói, đây không phải là những gì GIF được tạo ra; OGG sẽ là lựa chọn tốt hơn.)
wchargein

1
Re. "Nơi tất cả bộ nhớ đang hoạt động": 65 Kb là kích thước tệp của hình ảnh nén. Khi không nén, hình ảnh mất khoảng 4 x chiều rộng x chiều cao byte, do đó, hình ảnh 1024x768 sẽ chiếm ~ 3Mb RAM. Nhân số đó với "một vài nghìn" và bạn sẽ thấy bộ nhớ sẽ đi về đâu ...
Sergey

Câu trả lời:


33

Có vẻ như bạn đang cố gắng tạo một video. Nếu đó là trường hợp, thì tôi sẽ sử dụng một định dạng video thích hợp.

Trong trường hợp này, tôi sẽ sử dụng ffmpeg để chuyển đổi các tệp PNG riêng lẻ thành video H.264. Vì ffmpeg được tạo để hoạt động với các video có thể kéo dài hàng giờ, nên nó không có vấn đề gì với hàng ngàn hình ảnh của bạn. Sử dụng H.264 thay vì gif hoạt hình sẽ dẫn đến sự cải thiện lớn về chất lượng hình ảnh.

Một cái gì đó như thế này sẽ làm việc cho bạn:

 ffmpeg -framerate 1/2 -i img%04d.png -c:v libx264 -r 30 out.mp4
  • -framerate 1/2: Điều này đặt tốc độ khung hình thành một nửa FPS, hoặc 2 giây mỗi khung hình.
  • -i img%04d.png: Điều này nói với ffmpeg để đọc các tập tin img0000.pngmặc dù img9999.png.
  • -c:v libx264: Sử dụng codec video libx264.
    • Bạn có thể chỉ định tham số nén video tại đây, nếu bạn muốn:
    • -crf <number>: Cài đặt chất lượng. 0 đến 51. 23 là mặc định. 0 là mã hóa lossless thực sự, sẽ có băng thông khá cao. 18 là gần như mất mát trực quan.
  • -r 30: Đặt tốc độ khung hình đầu ra thành 30 FPS. Mỗi hình ảnh đầu vào sẽ được nhân đôi để tạo đầu ra những gì bạn chỉ định ở đây. Bạn có thể bỏ tham số này và tệp đầu ra sẽ ở tốc độ khung hình đầu vào, nhưng phim kết quả không hiển thị đúng khi tôi thử nó ngay bây giờ.
  • out.mp4: Tên tệp xuất ra.

Tài liệu tham khảo:


1
Mở rộng tốt đẹp của câu trả lời Frantique từ ngày trước.
Anh Cả Geek

Đây là một ffmpeg đơn giản vs ImageMagick benchmark với dữ liệu thử nghiệm bê tông: askubuntu.com/questions/648244/...
Ciro Santilli新疆改造中心法轮功六四事件

11

Cá nhân, tôi sẽ chỉ khởi chạy nó với số lượng tệp giới hạn thay vì tất cả cùng một lúc. Ví dụ, một cái gì đó như thế này:

#!/usr/bin/env bash

## Collect all png files in the files array
files=( *png )
## How many should be done at once
batch=50

## Read the array in batches of $batch
for (( i=0; $i<${#files[@]}; i+=$batch ))
do
    ## Convert this batch
    convert -delay 2 -loop 0 "${files[@]:$i:$batch}" animated.$i.gif
done

## Now, merge them into a single file
convert  animated.*.gif all.gif

8

Sử dụng -limit memory 1GiBđể giới hạn số lượng bộ nhớ convertsử dụng.

1000 hình ảnh sẽ tạo ra một GIF khổng lồ mà hầu hết các máy tính sẽ phải vật lộn để hiển thị. Tôi giữ GIF động của mình dưới 200 hình ảnh khi có thể. Càng ít càng tốt. Nếu bạn đánh số hình ảnh của mình, lệnh này sẽ xóa các hình ảnh được đánh số lẻ rm *[13579].png.

Vì vậy, đây là quy trình công việc điển hình của tôi để tạo GIF động từ cảnh phim:

avconv -ss 00:26:00 -i someMovie.mpg %5d.png
rm  *[13579].png
convert -limit memory 1GiB -loop 0 -layers optimize -resize 400 *.png output.gif

1
Cảm ơn bạn, giải pháp đó hoạt động tốt. Cũng có thể cần phải tăng giới hạn bộ nhớ được phép trong /etc/ImageMagick-6/policy.xml xem github.com/ImageMagick/ImageMagick/issues/iêu để biết thêm thông tin
Louis Gagnon

4

Tôi có thể sử dụng định dạng mở khác nếu .gif không được hỗ trợ

Có lẽ APNG là sử dụng cho bạn. Nó được hỗ trợ bởi một số trình duyệt , bao gồm cả Firefox nhưng hiện tại không bao gồm Chrome và IE. Vì chỉ là phần mở rộng PNG, nên việc chuyển đổi PNG sang APNG rất đơn giản. Công cụ apngasm có thể làm điều đó. Nhưng định dạng đơn giản đến mức gần đây tôi đã tự viết một trình biên dịch APNG cho Sage. Thích ứng với mã đó sẽ là một sự thay thế.


Tôi cũng muốn chỉ ra rằng APNG là không chuẩn và mặc dù đã tồn tại được 7 năm vẫn còn rất mù mờ.
Pharap

Đối với một minh chứng khoa học, nơi bạn có thể chọn trình duyệt được sử dụng cho nó, đây vẫn có thể là một giải pháp đơn giản và mạnh mẽ.
MvG

Nó phụ thuộc vào người phải xem cuộc biểu tình. Sẽ rất tốt nếu trao bản sao cho người xem và sau đó hai phần ba phải tắt và tải xuống Firefox chỉ để xem. Không phải là loại ấn tượng tôi muốn tạo ra nếu tôi đang thực hiện một minh chứng khoa học quan trọng. Nếu nó chỉ được xem là một phần của cuộc biểu tình thì đủ công bằng, nhưng nó có thể không phù hợp với các tình huống khác.
Pharap

3

Nếu bạn có hàng ngàn png-s, định dạng anigif là lạ. Tôi sẽ làm theo cách này, sử dụng avconv:

 avconv -i "%d.png" -r 25 -c:v libx264 -crf 20 -pix_fmt yuv420p animated.mov

Cách tiếp cận này có thêm lợi ích mà sau này bạn có thể chuyển sang âm thanh giọng nói hoặc âm nhạc không thể có với Định dạng trao đổi đồ họa.
Anh Cả Geek

2

gifsicle là một tiện ích dòng lệnh để xử lý hoạt ảnh GIF. Nếu bạn sẵn sàng trao đổi bộ nhớ để lấy tốc độ, bạn có thể sử dụng công tắc --conserve-memory của nó.


Để tôi nói theo cách này: gifsicle đã có dấu chân nhỏ hơn ImageMagick - nếu bạn thấy rằng nó vẫn sử dụng quá nhiều bộ nhớ cho nhiệm vụ trong tay, thì bạn có thể sử dụng --conserve-memory
codehead 16/1/2015

Ồ, tôi nghĩ rằng tôi đã đọc sai những gì bạn đang nói, rằng công tắc sẽ sử dụng nhiều bộ nhớ hơn, điều này không có ý nghĩa nhiều. đừng bận tâm.
tò mò

2

Ngoài các câu trả lời khác: vì bạn muốn tạo tệp GIF, tôi giả sử bạn muốn hiển thị hình ảnh trên trang web. Nếu vậy, tôi sẽ không buồn chuyển đổi PNG của bạn cả. Chỉ cần google cho "trình chiếu javascript" và sử dụng một trong hàng triệu tập lệnh miễn phí. Hoặc viết của riêng bạn, điều này thực sự tầm thường.

Những lợi ích của việc làm theo cách này là:

  • chỉ có một hình ảnh được tải trong trình duyệt bất cứ lúc nào, trình chiếu bắt đầu nhanh và không tiêu tốn nhiều RAM trên máy của người dùng.

  • các giải pháp quy mô đến hàng triệu hình ảnh. Hoặc hàng tỷ, nếu bạn đủ kiên nhẫn để xem tất cả :)

  • Bạn có thể thêm các điều khiển vào trang của mình để tạm dừng, tua lại, thay đổi độ trễ hoặc chuyển đến một khung cụ thể.


Cảm ơn bạn. Trong thực tế, điều này không phải để hiển thị trên một trang web. +1 cho ý tưởng, mặc dù.
dotancohen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.