แยกดัชนีของคีย์เฟรมจากวิดีโอโดยใช้ ffmpeg


17

ฉันใช้ ffmpeg เพื่อแยกเฟรมหลักออกจากวิดีโอ นี่คือคำสั่ง:

ffmpeg -i test2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 160x90 -f image2 thumbnails-%02d.jpeg

ฉันจะดึงดัชนีของแต่ละเฟรมหลักที่แยกในวิดีโอได้อย่างไร ตัวอย่างเช่นสำหรับ I-frame แรกดัชนีจะเป็น 0 สำหรับวินาทีมันจะเป็น 24 เป็นต้น


เป็นไปได้ซ้ำกันของsuperuser.com/questions/669716/…
user236012

ดูที่การใช้ ffprobe จากนั้นโพสต์ประมวลผลเอาต์พุตเพื่อรับดัชนี?
dstob

@dstob คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับสิ่งที่คุณหมายถึง? ฉันยังใหม่กับ ffmpeg
Faten Khalifa

@LordNeckbeard หมายเลขเฟรมในเฟรมวิดีโอเช่น เฟรมแรกของวิดีโอจะอยู่ที่ดัชนี 0 ฉันต้องการทราบดัชนีของแต่ละคีย์เฟรมในเฟรมวิดีโอ
Faten Khalifa

คุณต้องการพิมพ์หมายเลขเฟรมบนภาพขนาดย่อ (บนภาพ)
llogan

คำตอบ:


21

เช่นเดียวกับ @dstob ที่กล่าวถึงคุณสามารถใช้ffprobeเพื่อรับ I-frames และข้อมูลที่เกี่ยวข้อง ffprobeมาพร้อมกับบิลด์สแตติกบางส่วนในหน้าดาวน์โหลดและสามารถสร้างได้จากซอร์สเช่นกัน

นี่สมมติว่าคุณใช้ Linux / Unix:

แยกเฟรมและประเภทเฟรม

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1

grepคำสั่งกรองเส้นที่มีIในพวกเขาและพวกเขานับดัชนี (โดยใช้-nตัวเลือก) cutคำสั่งเลือกคอลัมน์แรกของการส่งออกเท่านั้น (ดัชนี) โปรดทราบว่าดัชนีนี้ใช้แบบ 1 ไม่ใช่ไม่ใช่แบบ 0

เปลี่ยนชื่อไฟล์เอาต์พุตตามดัชนี

จริง ๆ แล้วคุณสามารถไพพ์ดัชนีเหล่านี้ไปยังรายการ:

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1 > frame_indices.txt

จากนั้นทำรายการภาพขนาดย่อทั้งหมดด้วย:

ls -1 thumbnails*.jpeg > thumbnails.txt

จากนั้นวางทั้งสองเข้าด้วยกัน:

paste thumbnails.txt frame_indices.txt > combined.txt

รายการตอนนี้มีชื่อของภาพขนาดย่อและดัชนี ดำเนินการเปลี่ยนชื่อตาม:

while read -r thumbnail index; do
  newIndex=$(echo $index - 1 | bc) # subtract 1 from the index
  mv -- "$thumbnail" "thumbnail-$newIndex.jpeg"  # rename file
done < combined.txt

ข้างต้นจะเปลี่ยนชื่อไปthumbnail-01.jpeg thumbnail-0.jpegโปรดทราบว่าไม่มีการเติมเต็มศูนย์ในดัชนีผลลัพธ์ หากคุณต้องการ zero-pad ให้พูดถึง 5 หลักให้ใช้printf:

newIndex=$(printf '%05d' $(echo $index - 1 | bc))

ใน Windows คุณต้องทำสิ่งเดียวกันด้วยffprobeแต่แยกวิเคราะห์ผลลัพธ์ต่างกัน ไม่รู้ว่าจะทำการเปลี่ยนชื่อที่นั่นได้อย่างไร


ข้อผิดพลาดนี้จะปรากฏขึ้น: 'grep' ไม่ได้รับการยอมรับว่าเป็นคำสั่งภายในหรือภายนอกโปรแกรมที่ทำงานได้หรือไฟล์แบตช์
Faten Khalifa

2
นั่นเป็นเพราะคุณอยู่บน Windows อย่างที่ฉันพูดคำตอบนี้ถือว่า Linux หรือ Unix คุณไม่ได้เจาะจงมากขึ้นในคำถามของคุณ คุณสามารถทำสิ่งเดียวกันบน Windows โดยใช้Cygwinหรือเลเยอร์ GNU / Linux ที่คล้ายกันสำหรับ Windows
slhck

นี่คือความช่วยเหลืออย่างมากขอบคุณ การแก้ไขเดียว: ฉันคิดว่าดัชนีในคำสั่งแรกของคุณปิดด้วยปัจจัยสามประการเนื่องจากมี[FRAME]บรรทัดและ[/FRAME]บรรทัดสำหรับทุกpict_typeบรรทัด
Jack O'Connor

2
@ JackO'Connor มีเพียงหนึ่งบรรทัดต่อกรอบคือถ้าคุณใช้ตัวเลือกสำหรับการ-of csv ffprobeสิ่งที่คุณกำลังอธิบายคือรูปแบบเอาต์พุตเริ่มต้น
slhck

0

หากคุณต้องการใช้ FFMPEG ตามที่ระบุไว้ในตอนแรกคุณสามารถแสดงรายการทั้งหมดหรือบางส่วนรวมทั้งสร้าง jpg ด้วยรายการต่อไปนี้:

ffmpeg.exe \
  -i "C:\Users\UserName\Desktop\jpegs and list\VideoName.mp4" \
  -t 15 \
  -vf select="eq(pict_type\,PICT_TYPE_I)" \
  -vsync 2 \
  -s 160x90 \
  -f image2 thumbnails-%02d.jpeg \
  -loglevel debug 2>&1| for /f "tokens=4,8,9 delims=. " %d in ('findstr "pict_type:I"') do echo %d %e.%f>>"keyframe_list.txt"

ลบโดย-t 15ไม่ จำกัด เวลาหรือเปลี่ยนให้เหมาะสม ลบ-s 160x90 -f image2 thumbnail-%02d.jpegหรือเปลี่ยนแปลงเพื่อให้เหมาะกับการลบภาพขนาดย่อ


ใน Windows 7 CMD สิ่งนี้จะล้มเหลวที่ \ การเปลี่ยน \ เป็น ^ ทำให้เกิดความล้มเหลวที่: I "คุณมีรุ่นที่ทำงานบน Windows ได้ไหม?
ChrisJJ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.