Làm thế nào để loại bỏ mọi khung hình thứ hai từ một gif hoạt hình?


22

Tôi có một thư mục chứa đầy các video mà tôi muốn chuyển đổi thành một gifs hoạt hình. ffmpeg / avconv thực hiện công việc không tốt khi thực hiện trực tiếp, vì vậy tôi thay đổi video thành gif bằng cách đầu tiên xuất từng khung hình thành png và sau đó chuyển đổi lại thành gif bằng hình ảnh. Vấn đề là điều này dẫn đến một gif lớn về kích thước tệp. Để giải quyết vấn đề này, tôi muốn "thả" từng khung hình thứ hai hoặc thứ n khỏi gif, bằng cách bỏ qua mọi tệp hình ảnh khi chuyển đổi sang gif hoặc bằng cách xóa khung hình khỏi gif. Làm cách nào tôi có thể thực hiện việc này trên Ubuntu (13.04) bằng cách sử dụng hình ảnh hoặc một số tiện ích dòng lệnh khác?

Câu trả lời:


14

Sử dụng tập lệnh bash

Để thực hiện việc này từ dòng lệnh, bạn có thể sử dụng tiện ích có tên Gifsicle . Không có phương thức tích hợp nào để xóa mọi khung hình khác, vì vậy bạn sẽ cần làm bẩn tay với một số tập lệnh.

Đây là một kịch bản nhanh mà tôi đã thực hiện để làm một GIF duy nhất:

#!/bin/bash
# This script will take an animated GIF and delete every other frame
# Accepts two parameters: input file and output file
# Usage: ./<scriptfilename> input.gif output.gif

# Make a copy of the file
cp $1 $2

# Get the number of frames
numframes=`gifsicle $1 -I | grep -P "\d+ images" --only-matching | grep -P "\d+" --only-matching`

# Deletion
let i=0
while [[ $i -lt $numframes  ]]; do
    rem=$(( $i % 2 ))

    if [ $rem -eq 0 ]
    then
        gifsicle $2 --delete "#"$(($i/2)) -o $2 
    fi

    let i=i+1 
done

Tôi đã thử nghiệm nó với một GIF đếm ngược đơn giản:

nhập mô tả hình ảnh ở đây

Và đây là kết quả sau khi chạy nó thông qua kịch bản:

nhập mô tả hình ảnh ở đây

Kịch bản này tất nhiên là không chống đạn, nhưng nó sẽ đưa bạn đi đúng hướng.


Lưu ý rằng vòng lặp xóa của bạn có thể được đơn giản hóa thànhlet i=0; while [[ $i -lt $(($numframes / 2)) ]]; do gifsicle $2 --delete "#$i" -o $2; let i=i+1; done
Ilmari Karonen

1
Thực tế, bạn hoàn toàn không cần một vòng lặp: gifsicle "$1" --unoptimize $(seq -f "#%g" 0 2 $numframes) -O2 -o "$2"sẽ thực hiện trong một cuộc gọi.
Ilmari Karonen

Tôi thực sự không biết làm thế nào để chạy tập lệnh này từ dòng lệnh. Tôi đã cố lưu nó dưới dạng tệp gifdrop.sh và chạy nó theo hướng dẫn trong cách sử dụng (./gifdrop.sh in.gif out.gif) trên một gif có tên in.gif và nó cho biết lệnh gifdrop không rõ
mapsvers

@mematvers bạn đã làm cho tập tin thực thi? chmod +x gifdrop.sh
JohnB

1
Hoạt động tốt hơn trên macOS: github.com/colindean/hejmo/blob/master/scripts/iêu - phiên bản của tôi sử dụng perl thay vì grep để nó hoạt động trên macOS không cài đặt GNU grep theo mặc định. Ngoài ra, xử lý không gian trong tên tập tin.
Colin Dean

27

Đây là một giải pháp đơn giản hơn bằng cách sử dụng gifsicle so với tập lệnh của JohnB :

gifsicle -U input.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif

Lệnh này sẽ hoạt động trong hầu hết các shell Unix; Tôi đã thử nó trong bash. Thay thế input.gifoutput.gifbằng tên tệp đầu vào và đầu ra, và 99với số lượng khung trong hoạt hình của bạn. (Bạn có thể sử dụng số lượng lớn hơn, nhưng gifsicle sẽ phàn nàn về điều đó.)

Một số lưu ý:

  • Công -Utắc sẽ hợp nhất các khung trong hoạt hình đầu vào với các khung trước, để mỗi khung đứng độc lập và không phụ thuộc vào bất kỳ khung nào khác. Bạn thực sự muốn làm điều này trước khi làm bất cứ điều gì với hoạt hình, nếu không bạn có thể nhận được kết quả lộn xộn. (Nếu hình động đầu vào của bạn đã không được tối ưu hóa, gifsicle có thể in cảnh báo về nó, nhưng điều này cũng hoàn toàn vô hại.)

  • Ngược lại, công -O2tắc tối ưu hóa lại hình ảnh động đầu ra để giảm thiểu kích thước tệp. Với hoạt hình mẫu của JohnB, nó thu nhỏ kích thước đầu ra xuống 27%.

  • Các seqlệnh chỉ xuất ra một chuỗi các số từ 0 đến 99, đếm lên trong các bước của 2. -f "#%g"làm cho nó in một #trước mỗi số, mà làm cho gifsicle hiểu nó như là một lựa chọn khung thay vì một tên tập tin. Backticks ( `) xung quanh lệnh seq khiến đầu ra của nó được đưa vào làm tham số trong dòng lệnh gifsicle.

Nếu bạn không muốn gif tăng tốc, bạn có thể sử dụng gifsicle -I input.gifđể có được độ trễ khung hình hiện tại, nhân nó với 2 và sử dụng gifsicle -d ${delay} ....


Làm tốt lắm! Nếu bạn thực sự muốn, bạn có thể sử dụng grep từ tập lệnh của tôi để đưa ra chính xác số lượng khung hình (và thực hiện một lệnh của lệnh). Hoặc có lẽ có một cách đơn giản hơn để trả về số lượng khung hình trong một GIF hoạt hình?
JohnB

3
Cuối cùng tôi đã thực hiện một mệnh lệnh của một mệnh lệnh, @JohnB -gifsicle input.gif `seq -f "#%g" 0 2 $(identify input.gif | tail -1 | cut -d "[" -f2 - | cut -d "]" -f1 -)` --unoptimize -O2 -o output.gif
Kasra Rahjerdi

Trên Windows 7 x64 với phiên bản 1.71, tôi đã nhận được : useless unoptimization-related input option. Vì vậy, tôi đã làm điều đó trong hai bước (từ bên trong Git Bash): 1. gifsicle -U -o unoptimized.gif input.gif2.gifsicle unoptimized.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif
feklee

11

LƯU Ý : Câu trả lời này đã được đăng trước khi có yêu cầu về dòng lệnh / nguồn mở, nhưng tôi sẽ bỏ nó vì nó có thể giúp người khác trong tương lai


Sử dụng Photoshop

Đây không phải là một giải pháp nguồn mở hoặc dòng lệnh, nhưng bạn có thể làm điều này với Photoshop:

Tập tinnhậpFrames Video to Layers ...

Nhập video

" Giới hạn cho mỗi __ khung " sẽ thực hiện thủ thuật cho bạn


0

Đây là giải pháp của tôi bằng cách sử dụng xử lý tập lệnh bó ...

Trước tiên, sao chép gif hoạt hình gốc đã chụp vào tệp input.gif sau đó bắt đầu trình thông dịch lệnh và gõ:

gifsicle input.gif -I "# -1"> input.txt

nhìn vào input.txt và xem độ dài của hình ảnh động là bao nhiêu - nó chứa bao nhiêu khung hình ...

input.txt:

* input.gif 166 images
  logical screen 1366x768
  global color table [256]
  background 15
  loop forever
  + image #165 1x1 at 1365,767 transparent 15
    disposal asis delay 0.07s

sau đó chỉnh sửa-tạo test.bat và thay đổi giá trị của biến len = spec_length_number_from_input.txt và lưu test.bat ...

kiểm tra.bat:

@echo off
set /A len=166
set /A i=1
set /A ii=0
:loop
if %i%==%len% goto :eof
if %ii%==0 (set /A ii=1) else (set /A ii=0)
set /A iii=%ii%*%i%
if %i%==%iii% echo gifsicle -b input.gif --delete "#1" --done
set /A i=%i%+1
goto :loop

sau đó cuối cùng bắt đầu process1.bat và process2.bat và cắt hình động với mọi khung hình lẻ sẽ được xử lý thành tệp input.gif

process1.bat:

gifsicle -b -U input.gif
test.bat > input.bat

process2.bat:

call "input.bat"
gifsicle -b -O2 input.gif
erase "input.bat"

0

Tôi nghĩ rằng tôi cần một lời giải thích mới phức tạp hơn (độ trễ khung hình cũng là điều quan trọng cũng cần được xem xét) ... Đối với quy trình mới này, bạn sẽ cần tải xuống JREPL.BAT từ liên kết này: http://www.dostips.com /forum/viewtopic.php?t=6044

Trước tiên, sao chép gif đã chụp vào tệp input.gif, sau đó bắt đầu trình thông dịch lệnh và gõ:

gifsicle input.gif -I "# -1"> input.txt

nhìn vào input.txt và xem độ dài của hình ảnh động là bao nhiêu - nó chứa bao nhiêu khung hình ... cũng xem xét độ trễ của khung hình và nếu 0,07 của nó có nghĩa là bạn nên đặt tùy chọn -d14 (7msec * 2) vào dòng này trong process.cmd: gifsicle -b -U -d14 input.gif, sau khi chỉnh sửa lưu process.cmd

sau đó chỉnh sửa test.bat và thay đổi giá trị của biến 166 từ dòng này để khớp với số khung hình của hình động: for / L %% i IN (1,2,166) DO echo "# %% i" >> input.bat, sau chỉnh sửa lưu test.bat ...

sau đó bắt đầu process.cmd và cắt hình động với mọi khung hình lẻ sẽ được xử lý thành tệp input.gif

PS Ưu điểm của phương pháp này là bạn có toàn quyền kiểm soát những gì bạn muốn xóa khỏi gif (mỗi khung hình thứ hai (1,2,166) hoặc mỗi thứ ba (1,3,166)), và cứ thế thay đổi số giữa dòng lô, nhưng lưu ý rằng nếu bạn chỉ định (1,3,166), bạn nên thay đổi -d14 (tùy chọn độ trễ) từ process.cmd để phản ánh thay đổi (7msec * 3/2 = 10), vì vậy thay vì (7msec * 2 / 1 = 14), tùy chọn cho độ trễ phải là -d10 ...

Các tệp khác (ví dụ: xóa mọi khung hình thứ hai): test.bat:

@echo off
echo gifsicle -b input.gif --delete>> input.bat
for /L %%i IN (1,2,166) DO echo  "#%%i">> input.bat
echo  --done>> input.bat
call jrepl.bat "\n" "" /x /m /f input.bat /o -

quá trình.cmd:

gifsicle -b -U -d14 input.gif
call "test.bat"
call "input.bat"
gifsicle -b -O3 input.gif
erase "input.bat"

Và tập tin trợ giúp readme input.txt:

* input.gif 166 images
  logical screen 1366x768
  global color table [256]
  background 15
  loop forever
  + image #165 1x1 at 1365,767 transparent 15
    disposal asis delay 0.07s
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.