วิธีเปลี่ยน framerate ของวิดีโอโดยไม่ต้องเข้ารหัสใหม่


14

ฉันกำลังพยายามเปลี่ยนเฟรมวิดีโอ MP4 (เป็นวิดีโอ GoPro 120fps ฉันต้องการเล่นที่ 30 เฟรมต่อวินาทีเพื่อให้เอฟเฟ็กต์สโลว์โมชั่น)

ฉันใช้ avconv สำหรับสิ่งนี้:

avconv -i SourceMovie.mp4 -vf setpts=4.0*PTS -r 30 DestMovie.mp4

ใช้งานได้ทางเทคนิค แต่มัน reencodes ภาพยนตร์ นอกเหนือจากความเชื่องช้าแล้วยังเป็นปัญหาด้านคุณภาพอีกด้วย ในทางเทคนิคควรมีวิธีตั้ง fps ในส่วนหัวของวิดีโอฉันจะเปลี่ยนได้อย่างไร (เครื่องมืออื่นที่ไม่ใช่ avconv ก็ใช้ได้เช่นกัน)

คำตอบ:


15

MP4Boxสามารถทำได้

คำสั่ง

MP4Box -add SourceMovie.mp4#video -raw 1 -new test

สร้างไฟล์และtest test_track1.h264ตอนนี้คุณสามารถสร้างไฟล์ mp4 ซึ่งรองรับ framerate อะไรก็ได้ที่คุณต้องการ (30 ในตัวอย่างนี้):

MP4Box -add test_track1.h264:fps=30 -new DestMovie.mp4

MP4Box เป็นส่วนหนึ่งของgpacแพ็คเกจดังนั้นโปรดตรวจสอบให้แน่ใจว่าติดตั้งแล้ว


6
มันไม่ตรงไปตรงมาจริงๆ แต่ฉันเข้าใจแล้ว - คุณต้องทำสองขั้นตอน ขั้นแรกให้แยกสตรีมวิดีโอแยกเป็น raw ( MP4Box -add source.mp4#video -raw 1 -new test) จากนั้นบันทึกเป็น MP4 อีกครั้ง ( MP4Box -add test_track1.h264:fps=30 -new dest.mp4) คุณสามารถเพิ่มแทร็กเสียงได้ด้วย (ผ่าน #audio)
EboMike

มันจะดีกว่าที่จะใช้-singleตัวเลือกสำหรับคำสั่งแรก MP4Box -single 1 -raw 1 SourceMovie.mp4สร้างเพียงหนึ่งไฟล์SourceMovie_track1.h264แทนที่จะเป็นสองไฟล์
diversenok

6

การเปลี่ยนเฟรมในส่วนหัวของวิดีโอ (คอนเทนเนอร์) ไม่มีผลกับ videostream (หรือ audiostream) การเข้ารหัสซ้ำเป็นเพียงตัวเลือกเดียว

Videostreams มีการประทับเวลาและในวิดีโอส่วนใหญ่เฟรมจะพึ่งพาซึ่งกันและกันเนื่องจากการบีบอัดเฟรม ผู้เล่นบางคนสามารถเร่งความเร็วและทำให้วิดีโอช้าลง แต่ไม่ใช่ด้วยคำสั่งแบบฝังหรือบางอย่าง ผู้เล่นไม่สามารถเปลี่ยน framerate ได้ทันทีเมื่อคำสั่ง container ขอให้ทำเช่นนั้น วิดีโอเทปจะจบลงด้วยการกำหนด (เช่นไม่ปฏิบัติตามมาตรฐาน) และ 99.9% ของผู้เล่นจะปฏิเสธที่จะปฏิบัติตาม มันเป็นไปไม่ได้เลยทีเดียวที่จะทำสิ่งที่คุณต้องการโดยไม่ต้องบันทึกใหม่ แน่นอนคุณสามารถรอด้วยการบันทึกจนกระทั่งขั้นตอนสุดท้ายในการแก้ไขของคุณ


1
ขอบคุณนะ! คำถามงี่เง่า - ทำไม? แต่ละเฟรมมีการประทับเวลาที่บังคับให้ผู้เล่นบังคับใช้ความเร็วในการเล่นหรือไม่? ฉันต้องการเฟรมเดียวกันแน่นอนฉันแค่ต้องการให้พวกเขาเล่นในอัตราที่แตกต่างกัน
EboMike

2
สวัสดีไมค์คำถามของคุณไม่ได้โง่ตรงไปตรงมาในแบบที่คุณคิดว่าค่อนข้างฉลาด ฉันชอบวิธีคิดของคุณ ฉันเพิ่มข้อมูลเพิ่มเติมลงในคำตอบของฉันเพราะมันยาวเกินไปที่จะใส่ลงในกล่องความคิดเห็น

ขอบคุณ! นั่นเป็นข้อมูลที่ค่อนข้าง ทีนี้สำหรับการเขียนใหม่ - วิธีที่ดีที่สุดในการทำเช่นนี้กับ avconv คืออะไร? ฉันใช้บรรทัดคำสั่งด้านบน แต่นั่นทำให้มีคุณภาพแย่มาก - ฉันเกือบจะเห็น macroblock ทุกตัว
EboMike

1
ฉันคิดว่า timestamps ในวิดีโอสตรีมนั้นไม่ได้เป็นบิตสตรีมดิบ h.264 bit เอง ตราบใดที่คุณต้องการเปลี่ยนเวลา แต่ไม่ใช่ลำดับของเฟรมที่จะแสดงเมื่อใดคุณไม่จำเป็นต้องแปลงรหัสเพียงแค่เปลี่ยนใหม่ (และถ้าคุณทำ xcode ด้วยฮาร์ดแวร์ที่เร็วกว่าคุณต้องใช้ -preset ช้ากว่าหรือช้ามากเพื่อให้ได้คุณภาพมากขึ้นที่บิตเรตเดียวกันแทนการขว้างบิตเพิ่มเติมที่ปัญหาและใช้ -crf 18 หรือบางอย่างไม่ใช่ ABR)
Peter Cordes

1
ฉันไม่สามารถหาวิธีรับ ffmpeg เพื่อส่งออกอัตราเฟรมที่แตกต่างกันได้ ดูเหมือนว่าจำเป็นต้องมี mkvmerge / mp4box เว้นแต่คุณจะได้รับ ffmpeg เพื่อเอาท์พุท bit 0.26 ดิบจากนั้นใช้ตัวเลือก fps เพื่อ demuxer h.264 (ซึ่งเอกสารเต็ม -h มีเนื่องจาก bitstream ไม่มีเวลา ข้อมูลเพียงแค่สั่งซื้อ)
Peter Cordes

3

ในกรณีที่ความตั้งใจหลักของคุณคือเล่นแบบสโลว์โมชั่นและไม่เก็บไฟล์เป็น MP4 คุณสามารถใช้เครื่องมือ MKVmerge GUI เพื่อทำการรีมมันลงในคอนเทนเนอร์ Matroska ซึ่งสามารถเปลี่ยนเฟรมได้อย่างง่ายดาย การ remuxing นั้นดีกว่าการเข้ารหัสซ้ำเพราะจะเปลี่ยนเฉพาะข้อมูลเมตาเท่านั้น

ก่อนอื่นให้คุณติดตั้งแพ็คเกจ

sudo apt-get install mkvtoolnix-gui

จากนั้นคุณเริ่ม MKVmerge GUI คุณจะต้องเจอกับหน้าต่างแบบนี้

mkvmerge gui 1

เพียงแค่กดปุ่มเพิ่มและเลือกไฟล์ของคุณหรือเพียงแค่ลากและวางไฟล์ลงในพื้นที่ "อินพุตไฟล์" ณ จุดนี้คุณควรเลือกสตรีมวิดีโอในวิดีโอของคุณ นอกจากนี้คุณยังสามารถลบสตรีมอื่น ๆ ได้เนื่องจากพวกเขาจะเข้ามาในทางใดทางหนึ่ง

หลังจากที่คุณเลือกแล้วคุณจะเห็นแท็บด้านล่างเริ่มทำงาน:

ป้อนคำอธิบายรูปภาพที่นี่

เปลี่ยนเป็น "จัดรูปแบบการกระทำเฉพาะ"

ป้อนคำอธิบายรูปภาพที่นี่

คุณจะเห็นว่ามีฟิลด์ "FPS" ซึ่งคุณสามารถป้อนค่าของเฟรมต่อวินาที ดูเหมือนว่าคุณวางแผนที่จะชะลอสิ่งต่าง ๆ ลงสี่ครั้งดังนั้นประมาณ 7 เฟรมต่อวินาทีจะเป็นเป้าหมายของคุณ คุณยังสามารถใช้ตัวเลือก "ยืดตาม"

หลังจากนั้นคุณสามารถเปลี่ยนชื่อไฟล์เอาต์พุต (ถ้าคุณต้องการ) และกด "เริ่ม muxing"

โปรแกรมจะทำงานและคุณควรมีไฟล์ของคุณ


2

ฉันยังต้องการที่จะลดความเร็วของภาพยนตร์ 120 FPS ของฉันเป็น 30 FPS ฉันสร้างสคริปต์ซึ่งทำได้โดยเปลี่ยนจังหวะเสียงและแก้ไข FPS โดยตรงในคอนเทนเนอร์ MP4 ต้องใช้เครื่องมือต่อไปนี้:

  1. avconvเพื่อแปลงกระแสข้อมูลเสียง
  2. sondstretchเพื่อชะลอความเร็วของเสียง
  3. gpacเพื่อรับMP4Boxเพื่อเปลี่ยน FPS

สคริปต์ที่ใช้สำหรับการแปลงอยู่ที่นี่:

#!/bin/bash
#########################################
# Lossless slow down from 120 to 30 FPS #
#                                       #
# Use:                                  #
#                                       #
#   slow.bash <mp4_file>                #
#                                       #
#                           #-= OSi =-# #
#########################################


# Prepare basic variables
IN_FILE="$1"
NAME=$(echo "${IN_FILE}" | sed 's/\.[^.]*//')


# Clean up before start
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264" "${NAME}_slow.mp4"


# Slow down sound
avconv -i "${IN_FILE}" -vn -acodec pcm_s16le "${NAME}_.wav"
soundstretch "${NAME}_.wav" "${NAME}.wav" -tempo=-75
avconv -i "${NAME}.wav" -vn -codec:a ac3_fixed -b:a 448k "${NAME}.ac3"


# Change video frame rate and multiplex with slowed sound
MP4Box -add "${IN_FILE}#video" -raw 1 -new "${NAME}"
MP4Box -add "${NAME}_track1.h264:fps=30" -add "${NAME}.ac3" -new "${NAME}_slow.mp4"


# Clean up when we are done
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264"

สคริปต์นี้สร้างสำเนาของ MP4 พร้อม _slow postfix

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