
Recherche avancée
Médias (91)
-
Richard Stallman et le logiciel libre
19 octobre 2011, par
Mis à jour : Mai 2013
Langue : français
Type : Texte
-
Stereo master soundtrack
17 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Audio
-
Elephants Dream - Cover of the soundtrack
17 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Image
-
#7 Ambience
16 octobre 2011, par
Mis à jour : Juin 2015
Langue : English
Type : Audio
-
#6 Teaser Music
16 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
-
#5 End Title
16 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
Autres articles (44)
-
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir -
Contribute to a better visual interface
13 avril 2011MediaSPIP is based on a system of themes and templates. Templates define the placement of information on the page, and can be adapted to a wide range of uses. Themes define the overall graphic appearance of the site.
Anyone can submit a new graphic theme or template and make it available to the MediaSPIP community. -
Submit bugs and patches
13 avril 2011Unfortunately a software is never perfect.
If you think you have found a bug, report it using our ticket system. Please to help us to fix it by providing the following information : the browser you are using, including the exact version as precise an explanation as possible of the problem if possible, the steps taken resulting in the problem a link to the site / page in question
If you think you have solved the bug, fill in a ticket and attach to it a corrective patch.
You may also (...)
Sur d’autres sites (5687)
-
I'm trying to hide information in a H264 video. When I stitch the video up, split it into frames again and try to read it, the information is lost
18 mai 2024, par Wer WerI'm trying to create a video steganography python script. The algorithm for hiding will be...


- 

- convert any video codec into h264 lossless
- save the audio of the video and split the h264 video into frames
- hide my txt secret into frame0 using LSB replacement method
- stitch the video back up and put in the audio










...and when I want to recover the text, I'll


- 

- save the audio of the video and split the encoded h264 video into frames
- retrieve my hidden text from frame0 and print the text






So, this is what I can do :


- 

- split the video
- hide the text in frame0
- retrieve the text from frame0
- stitch the video










But after stitching the video, when I tried to retrieve the text by splitting that encrypted video, it appears that the text has been lost. This is because i got the error


UnicodeEncodeError: 'charmap' codec can't encode character '\x82' in position 21: character maps to <undefined>
</undefined>


I'm not sure if my LSB replacement algorithm was lost, which results in my not being able to retrieve my frame 0 information, or if the H264 conversion command I used was a converted my video into H264 lossy version instead of lossless (which I don't believe so because I specified -qp 0)
This was the command I used to convert my video


ffmpeg -i video.mp4 -t 12 -c:v libx264 -preset veryslow -qp 0 output.mp4



These are my codes


import json
import os
import magic
import ffmpeg
import cv2
import numpy as np

import subprocess

# Path to the file you want to check
here = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(here, "output.mp4")
raw_video = cv2.VideoCapture(file_path)
audio_output_path = os.path.join(here, "audio.aac")
final_video_file = os.path.join(here, "output.mp4")

# create a folder to save the frames.
frames_directory = os.path.join(here, "data1")
try:
 if not os.path.exists(frames_directory):
 os.makedirs(frames_directory)
except OSError:
 print("Error: Creating directory of data")

file_path_txt = os.path.join(here, "hiddentext.txt")
# Read the content of the file in binary mode
with open(file_path_txt, "r") as f:
 file_content = f.read()
# txt_binary_representation = "".join(format(byte, "08b") for byte in file_content)
# print(file_content)

"""
use this cmd to convert any video to h264 lossless. original vid in 10 bit depth format
ffmpeg -i video.mp4 -c:v libx264 -preset veryslow -qp 0 output.mp4

use this cmd to convert any video to h264 lossless. original vid in 8 bit depth format
ffmpeg -i video.mp4 -c:v libx264 -preset veryslow -crf 0 output.mp4

i used this command to only get first 12 sec of video because the h264 vid is too large 
ffmpeg -i video.mp4 -t 12 -c:v libx264 -preset veryslow -qp 0 output.mp4

check for multiple values to ensure its h264 lossless:
1. CRF = 0
2. qp = 0
3. High 4:4:4 Predictive
"""


# region --codec checking. ensure video is h264 lossless--
def check_h264_lossless(file_path):
 try:
 # Use ffprobe to get detailed codec information, including tags
 result = subprocess.run(
 [
 "ffprobe",
 "-v",
 "error",
 "-show_entries",
 "stream=codec_name,codec_long_name,profile,level,bit_rate,avg_frame_rate,nb_frames,tags",
 "-of",
 "json",
 file_path,
 ],
 stdout=subprocess.PIPE,
 stderr=subprocess.PIPE,
 text=True,
 )
 # Check if the file is lossless
 metadata = check_h264_lossless(file_path)
 print(json.dumps(metadata, indent=4))

 # Check if the CRF value is available in the tags
 for stream in metadata.get("streams", []):
 if stream.get("codec_name") == "h264":
 tags = stream.get("tags", {})
 crf_value = tags.get("crf")
 encoder = tags.get("encoder")
 print(f"CRF value: {crf_value}")
 print(f"Encoder: {encoder}")
 return json.loads(result.stdout)
 except Exception as e:
 return f"An error occurred: {e}"


# endregion


# region --splitting video into frames--
def extract_audio(input_video_path, audio_output_path):
 if os.path.exists(audio_output_path):
 print(f"Audio file {audio_output_path} already exists. Skipping extraction.")
 return
 command = [
 "ffmpeg",
 "-i",
 input_video_path,
 "-q:a",
 "0",
 "-map",
 "a",
 audio_output_path,
 ]
 try:
 subprocess.run(command, check=True)
 print(f"Audio successfully extracted to {audio_output_path}")
 except subprocess.CalledProcessError as e:
 print(f"An error occurred: {e}")


def split_into_frames():
 extract_audio(file_path, audio_output_path)
 currentframe = 0
 print("Splitting...")
 while True:
 ret, frame = raw_video.read()
 if ret:
 name = os.path.join(here, "data1", f"frame{currentframe}.png")
 # print("Creating..." + name)
 cv2.imwrite(name, frame)
 currentframe += 1
 else:
 print("Complete")
 break


# endregion


# region --merge all back into h264 lossless--
# output_video_file = "output1111.mp4"


def stitch_frames_to_video(frames_dir, output_video_path, framerate=60):
 command = [
 "ffmpeg",
 "-y",
 "-framerate",
 str(framerate),
 "-i",
 os.path.join(frames_dir, "frame%d.png"),
 "-c:v",
 "libx264",
 "-preset",
 "veryslow",
 "-qp",
 "0",
 output_video_path,
 ]

 try:
 subprocess.run(command, check=True)
 print(f"Video successfully created at {output_video_path}")
 except subprocess.CalledProcessError as e:
 print(f"An error occurred: {e}")


def add_audio_to_video(video_path, audio_path, final_output_path):
 command = [
 "ffmpeg",
 "-i",
 video_path,
 "-i",
 audio_path,
 "-c:v",
 "copy",
 "-c:a",
 "aac",
 "-strict",
 "experimental",
 final_output_path,
 ]
 try:
 subprocess.run(command, check=True)
 print(f"Final video with audio created at {final_output_path}")
 except subprocess.CalledProcessError as e:
 print(f"An error occurred: {e}")


# endregion


def to_bin(data):
 if isinstance(data, str):
 return "".join([format(ord(i), "08b") for i in data])
 elif isinstance(data, bytes) or isinstance(data, np.ndarray):
 return [format(i, "08b") for i in data]
 elif isinstance(data, int) or isinstance(data, np.uint8):
 return format(data, "08b")
 else:
 raise TypeError("Type not supported")


def encode(image_name, secret_data):
 image = cv2.imread(image_name)
 n_bytes = image.shape[0] * image.shape[1] * 3 // 8
 print("[*] Maximum bytes to encode:", n_bytes)
 secret_data += "====="
 if len(secret_data) > n_bytes:
 raise ValueError("[!] Insufficient bytes, need bigger image or less data")
 print("[*] Encoding Data")

 data_index = 0
 binary_secret_data = to_bin(secret_data)
 data_len = len(binary_secret_data)
 for row in image:
 for pixel in row:
 r, g, b = to_bin(pixel)
 if data_index < data_len:
 pixel[0] = int(r[:-1] + binary_secret_data[data_index], 2)
 data_index += 1
 if data_index < data_len:
 pixel[1] = int(g[:-1] + binary_secret_data[data_index], 2)
 data_index += 1
 if data_index < data_len:
 pixel[2] = int(b[:-1] + binary_secret_data[data_index], 2)
 data_index += 1
 if data_index >= data_len:
 break
 return image


def decode(image_name):
 print("[+] Decoding")
 image = cv2.imread(image_name)
 binary_data = ""
 for row in image:
 for pixel in row:
 r, g, b = to_bin(pixel)
 binary_data += r[-1]
 binary_data += g[-1]
 binary_data += b[-1]
 all_bytes = [binary_data[i : i + 8] for i in range(0, len(binary_data), 8)]
 decoded_data = ""
 for byte in all_bytes:
 decoded_data += chr(int(byte, 2))
 if decoded_data[-5:] == "=====":
 break
 return decoded_data[:-5]


frame0_path = os.path.join(here, "data1", "frame0.png")
encoded_image_path = os.path.join(here, "data1", "frame0.png")


def encoding_function():
 split_into_frames()

 encoded_image = encode(frame0_path, file_content)
 cv2.imwrite(encoded_image_path, encoded_image)

 stitch_frames_to_video(frames_directory, file_path)
 add_audio_to_video(file_path, audio_output_path, final_video_file)


def decoding_function():
 split_into_frames()
 decoded_message = decode(encoded_image_path)
 print(f"[+] Decoded message: {decoded_message}")


# encoding_function()
decoding_function()




So I tried to put my decoding function into my encoding function like this


def encoding_function():
 split_into_frames()

 encoded_image = encode(frame0_path, file_content)
 cv2.imwrite(encoded_image_path, encoded_image)

#immediately get frame0 and decode without stitching to check if the data is there
 decoded_message = decode(encoded_image_path)
 print(f"[+] Decoded message: {decoded_message}")

 stitch_frames_to_video(frames_directory, file_path)
 add_audio_to_video(file_path, audio_output_path, final_video_file)




This returns my secret text from frame0. But splitting it after stitching does not return my hidden text. The hidden text was lost


def decoding_function():
 split_into_frames()
#this function is after the encoding_function(). the secret text is lost, resulting in charmap codec #can't encode error
 decoded_message = decode(encoded_image_path)
 print(f"[+] Decoded message: {decoded_message}")



EDIT :
So i ran the encoding function first, copied frame0.png out and placed it some where. Then I ran the decoding function, and got another frame0.png.


I ran both frame0.png into this python function


frame0_data1_path = os.path.join(here, "data1", "frame0.png")
frame0_data2_path = os.path.join(here, "data2", "frame0.png")
frame0_data1 = cv2.imread(frame0_data1_path)
frame0_data2 = cv2.imread(frame0_data2_path)

if frame0_data1 is None:
 print(f"Error: Could not load image from {frame0_data1_path}")
elif frame0_data2 is None:
 print(f"Error: Could not load image from {frame0_data2_path}")
else:

 if np.array_equal(frame0_data1, frame0_data2):
 print("The frames are identical.")
 else:
 print("The frames are different.")



...and apparently both are different. This means my frame0 binary got changed when I stitch back into the video after encoding. Is there a way to make it not change ? Or will h264 or any video codec change a little bit when you stitch the frames back up ?


-
Using FFmpeg to stitch together H.264 videos and variably-spaced JPEG pictures ; dealing with ffmpeg warnings
19 octobre 2022, par LB2Context


I have a process flow that may output either H.264 Annex B streams, variably-spaced JPEGs, or a mixture of two. By variably-spaced I mean where elapsed time between any two adjacent JPEGs may (and likely to be) different from any other two adjacent JPEGs. So an example of possible inputs are :


- 

stream1.h264
{Set of JPEGs}
stream1.h264 + stream2.h264
stream1.h264 + {Set of JPEGs}
stream1.h264 + {Set of JPEGs} + stream2.h264
stream1.h264 + {Set of JPEGs} + stream2.h264 + {Set of JPEGs} + ...
stream1.h264 + stream2.h264 + {Set of JPEGs} + ...
















The output needs to be a single stitched (i.e. concatenated) output in MPEG-4 container.


Requirements : No re-encoding or transcoding of existing video compression (One time conversion of JPEG sets to video format is OKay).


Solution Prototype


To prototype the solution I have found that ffmpeg has
concat
demuxer that would let me specify an ordered sequence of inputs that ffmpeg would then concatenate together, but all inputs must be of the same format. So, to meet that requirement, I :

- 

- Convert every JPEG set to an .mp4 using concat (and using
delay #
directive to specify time-spacing between each JPEG) - Convert every .h264 to .mp4 using
-c copy
to avoid transcoding. - Stitch all generated interim .mp4 files into the single final .mp4 using
-f concat
and-c copy
.








Here's the bash script, in parts, that performs the above :


- 

-
Ignore the
curl
comment ; that's from originally generating a 100 jpeg images with numbers and these are simply saved locally. What the loop does is it generates concat input file withfile sequence#.jpeg
directives andduration #
directive where each successive JPEG delay is incremented by 0.1 seconds (0.1 between first and second, 0.2 b/w 2nd and 3rd, 0.3 b/w 3rd and 4th, and so on). Then it runsffmpeg
command to convert the set of JPEGs to .mp4 interim file.

echo "ffconcat version 1.0" >ffconcat-jpeg.txt
echo >>ffconcat-jpeg.txt

for i in {1..100}
do
 echo "file $i.jpeg" >>ffconcat-jpeg.txt
 d=$(echo "$i" | awk '{printf "%f", $1 / 10}')
 # d=$(echo "scale=2; $i/10" | bc)
 echo "duration $d" >>ffconcat-jpeg.txt
 echo "" >>ffconcat-jpeg.txt
 # curl -o "$i.jpeg" "https://math.tools/equation/get_equaimages?equation=$i&fontsize=256"
done

ffmpeg \
 -hide_banner \
 -vsync vfr \
 -f concat \
 -i ffconcat-jpeg.txt \
 -r 30 \
 -video_track_timescale 90000 \
 video-jpeg.mp4



-
Convert two streams from .h264 to .mp4 via copy (no transcoding).


ffmpeg \
 -hide_banner \
 -i low-motion-video.h264 \
 -c copy \
 -vsync vfr \
 -video_track_timescale 90000 \
 low-motion-video.mp4

ffmpeg \
 -hide_banner \
 -i full-video.h264 \
 -c copy \
 -video_track_timescale 90000 \
 -vsync vfr \
 full-video.mp4



-
Stitch all together by generating another concat directive file.


echo "ffconcat version 1.0" >ffconcat-h264.txt
echo >>ffconcat-h264.txt
echo "file low-motion-video.mp4" >>ffconcat-h264.txt
echo >>ffconcat-h264.txt
echo "file full-video.mp4" >>ffconcat-h264.txt
echo >>ffconcat-h264.txt
echo "file video-jpeg.mp4" >>ffconcat-h264.txt
echo >>ffconcat-h264.txt

ffmpeg \
 -hide_banner \
 -f concat \
 -i ffconcat-h264.txt \
 -pix_fmt yuv420p \
 -c copy \
 -video_track_timescale 90000 \
 -vsync vfr \
 video-out.mp4












Problem (and attempted troubleshooting)


The above does produce a reasonable output — it plays first video, then plays second video with no timing/rate issues AFAICT, then plays JPEGs with time between each JPEG "frame" growing successively, as expected.


But, the conversion process produces warnings that concern me (for compatibility with players ; or potentially other IRL streams that may result in some issue my prototyping content doesn't make obvious). Initial attempts generated 100s of warnings, but with some arguments added, I reduced it down to just a handful, but this handful is stubborn and nothing I tried would help.


The first conversion of JPEGs to .mp4 goes fine with the following output :


Input #0, concat, from 'ffconcat-jpeg.txt':
 Duration: 00:08:25.00, start: 0.000000, bitrate: 0 kb/s
 Stream #0:0: Video: png, pal8(pc), 176x341 [SAR 3780:3780 DAR 16:31], 25 fps, 25 tbr, 25 tbn, 25 tbc
Stream mapping:
 Stream #0:0 -> #0:0 (png (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 0x7fe418008e00] using SAR=1/1
[libx264 @ 0x7fe418008e00] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2
[libx264 @ 0x7fe418008e00] profile High 4:4:4 Predictive, level 1.3, 4:4:4, 8-bit
[libx264 @ 0x7fe418008e00] 264 - core 163 r3060 5db6aa6 - H.264/MPEG-4 AVC codec - Copyleft 2003-2021 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=4 threads=11 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'video-jpeg.mp4':
 Metadata:
 encoder : Lavf58.76.100
 Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv444p(tv, progressive), 176x341 [SAR 1:1 DAR 16:31], q=2-31, 30 fps, 90k tbn
 Metadata:
 encoder : Lavc58.134.100 libx264
 Side data:
 cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
frame= 100 fps=0.0 q=-1.0 Lsize= 157kB time=00:07:55.33 bitrate= 2.7kbits/s speed=2.41e+03x 
video:155kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.800846%
[libx264 @ 0x7fe418008e00] frame I:1 Avg QP:20.88 size: 574
[libx264 @ 0x7fe418008e00] frame P:43 Avg QP:14.96 size: 2005
[libx264 @ 0x7fe418008e00] frame B:56 Avg QP:21.45 size: 1266
[libx264 @ 0x7fe418008e00] consecutive B-frames: 14.0% 24.0% 30.0% 32.0%
[libx264 @ 0x7fe418008e00] mb I I16..4: 36.4% 55.8% 7.9%
[libx264 @ 0x7fe418008e00] mb P I16..4: 5.1% 7.5% 11.2% P16..4: 5.6% 8.1% 4.5% 0.0% 0.0% skip:57.9%
[libx264 @ 0x7fe418008e00] mb B I16..4: 2.4% 0.9% 3.9% B16..8: 16.2% 8.8% 4.6% direct: 1.2% skip:62.0% L0:56.6% L1:38.7% BI: 4.7%
[libx264 @ 0x7fe418008e00] 8x8 transform intra:28.3% inter:3.7%
[libx264 @ 0x7fe418008e00] coded y,u,v intra: 26.5% 0.0% 0.0% inter: 9.8% 0.0% 0.0%
[libx264 @ 0x7fe418008e00] i16 v,h,dc,p: 82% 13% 4% 0%
[libx264 @ 0x7fe418008e00] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 20% 8% 71% 1% 0% 0% 0% 0% 0%
[libx264 @ 0x7fe418008e00] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 41% 11% 29% 4% 2% 3% 1% 7% 1%
[libx264 @ 0x7fe418008e00] Weighted P-Frames: Y:0.0% UV:0.0%
[libx264 @ 0x7fe418008e00] ref P L0: 44.1% 4.2% 28.4% 23.3%
[libx264 @ 0x7fe418008e00] ref B L0: 56.2% 32.1% 11.6%
[libx264 @ 0x7fe418008e00] ref B L1: 92.4% 7.6%
[libx264 @ 0x7fe418008e00] kb/s:2.50



The conversion of individual streams from .h264 to .mp4 generates two types of warnings each. One is
[mp4 @ 0x7faee3040400] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
, and the other is[mp4 @ 0x7faee3040400] pts has no value
.

Some posts on SO (can't find my original finds on that now) suggested that it's safe to ignore and comes from H.264 being an elementary stream that supposedly doesn't contain timestamps. It surprises me a bit since I produce that stream using NVENC API and clearly supply timing information for each frame via
PIC_PARAMS
structure :NV_STRUCT(PIC_PARAMS, pp); ...; pp.inputTimeStamp = _frameIndex++ * (H264_CLOCK_RATE / _params.frameRate);
, where#define H264_CLOCK_RATE 9000
and_params.frameRate = 30
.

Input #0, h264, from 'low-motion-video.h264':
 Duration: N/A, bitrate: N/A
 Stream #0:0: Video: h264 (High), yuv420p(progressive), 1440x3040 [SAR 1:1 DAR 9:19], 30 fps, 30 tbr, 1200k tbn, 60 tbc
Output #0, mp4, to 'low-motion-video.mp4':
 Metadata:
 encoder : Lavf58.76.100
 Stream #0:0: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1440x3040 [SAR 1:1 DAR 9:19], q=2-31, 30 fps, 30 tbr, 90k tbn, 1200k tbc
Stream mapping:
 Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
[mp4 @ 0x7faee3040400] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
[mp4 @ 0x7faee3040400] pts has no value
[mp4 @ 0x7faee3040400] pts has no value0kB time=-00:00:00.03 bitrate=N/A speed=N/A 
 Last message repeated 17985 times
frame=17987 fps=0.0 q=-1.0 Lsize= 79332kB time=00:09:59.50 bitrate=1084.0kbits/s speed=1.59e+03x 
video:79250kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.103804%
Input #0, h264, from 'full-video.h264':
 Duration: N/A, bitrate: N/A
 Stream #0:0: Video: h264 (High), yuv420p(progressive), 1440x3040 [SAR 1:1 DAR 9:19], 30 fps, 30 tbr, 1200k tbn, 60 tbc
Output #0, mp4, to 'full-video.mp4':
 Metadata:
 encoder : Lavf58.76.100
 Stream #0:0: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1440x3040 [SAR 1:1 DAR 9:19], q=2-31, 30 fps, 30 tbr, 90k tbn, 1200k tbc
Stream mapping:
 Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
[mp4 @ 0x7f9381864600] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
[mp4 @ 0x7f9381864600] pts has no value
[mp4 @ 0x7f9381864600] pts has no value0kB time=-00:00:00.03 bitrate=N/A speed=N/A 
 Last message repeated 17981 times
frame=17983 fps=0.0 q=-1.0 Lsize= 52976kB time=00:09:59.36 bitrate= 724.1kbits/s speed=1.33e+03x 
video:52893kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.156232%



But the most worrisome error for me is from stitching together all interim .mp4 files into one :


[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f9ff2010e00] Auto-inserting h264_mp4toannexb bitstream filter
Input #0, concat, from 'ffconcat-h264.txt':
 Duration: N/A, bitrate: 1082 kb/s
 Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1440x3040 [SAR 1:1 DAR 9:19], 1082 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
 Metadata:
 handler_name : VideoHandler
 vendor_id : [0][0][0][0]
Output #0, mp4, to 'video-out.mp4':
 Metadata:
 encoder : Lavf58.76.100
 Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1440x3040 [SAR 1:1 DAR 9:19], q=2-31, 1082 kb/s, 30 fps, 30 tbr, 90k tbn, 90k tbc
 Metadata:
 handler_name : VideoHandler
 vendor_id : [0][0][0][0]
Stream mapping:
 Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f9fe1009c00] Auto-inserting h264_mp4toannexb bitstream filter
[mp4 @ 0x7f9ff2023400] Non-monotonous DTS in output stream 0:0; previous: 53954460, current: 53954460; changing to 53954461. This may result in incorrect timestamps in the output file.
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f9fd1008a00] Auto-inserting h264_mp4toannexb bitstream filter
[mp4 @ 0x7f9ff2023400] Non-monotonous DTS in output stream 0:0; previous: 107900521, current: 107874150; changing to 107900522. This may result in incorrect timestamps in the output file.
[mp4 @ 0x7f9ff2023400] Non-monotonous DTS in output stream 0:0; previous: 107900522, current: 107886150; changing to 107900523. This may result in incorrect timestamps in the output file.
frame=36070 fps=0.0 q=-1.0 Lsize= 132464kB time=00:27:54.26 bitrate= 648.1kbits/s speed=6.54e+03x 
video:132296kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.126409%



I'm not sure how to deal with those non-monotonous DTS errors, and no matter what I try, nothing budges. I analyzed the interim .mp4 files using
ffprobe -show_frames
and found that the last frame of each interim .mp4 does not have DTS, while previous frames do. E.g. :

...
[FRAME]
media_type=video
stream_index=0
key_frame=0
pkt_pts=53942461
pkt_pts_time=599.360678
pkt_dts=53942461
pkt_dts_time=599.360678
best_effort_timestamp=53942461
best_effort_timestamp_time=599.360678
pkt_duration=3600
pkt_duration_time=0.040000
pkt_pos=54161377
pkt_size=1034
width=1440
height=3040
pix_fmt=yuv420p
sample_aspect_ratio=1:1
pict_type=B
coded_picture_number=17982
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
color_range=unknown
color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
[/FRAME]
[FRAME]
media_type=video
stream_index=0
key_frame=0
pkt_pts=53927461
pkt_pts_time=599.194011
pkt_dts=N/A
pkt_dts_time=N/A
best_effort_timestamp=53927461
...



My guess is that as concat demuxer reads in (or elsewhere in ffmpeg's conversion pipeline), for the last frame it sees no DTS set, and produces a virtual value equal to the last seen. Then further in pipeline it consumes this input, sees that DTS value is being repeated, issues a warning and offsets it with increment by one, which might be somewhat nonsensical/unrealistic timing value.


I tried using
-fflags +genpts
as suggested in this SO answer, but that doesn't change anything.

Per yet other posts suggesting issue being with incompatible
tbn
andtbc
values and possible timebase issues, I tried adding-time_base 1:90000
and-enc_time_base 1:90000
and-copytb 1
and nothing budges. The-video_track_timescale 90000
is there b/c it helped reduce those DTS warnings from 100s down to 3, but doesn't eliminate them all.

Question


What is missing and how can I get ffmpeg to perform conversions without these warnings, to be sure it produces proper, well-formed output ?


-
Revision 208aa6158b : Remove get_nonrd_var_based_fixed_partition function This function has been repl
9 avril 2015, par Jingning HanChanged Paths :
Modify /vp9/encoder/vp9_encodeframe.c
Remove get_nonrd_var_based_fixed_partition functionThis function has been replaced by other approaches and is not
in use now.Change-Id : I387f45b5607d202539e482468ccc70e6c0f9341f