Merge two videos with different HTTP Range header bytes - file

I want to save 10 seconds from any part of a video by using its URL (without downloading it completely).
the server supports the Range header and it's possible to get specific byte ranges, the video is ok when I save it with something like Range: bytes=0-102400 but when I change the start byte and save a video with Range: bytes=307200-614400 it's no longer playable.
I know maybe it lacks a MIME/header type that should be at the beginning of a file, but the first bytes are not in this response to specify the correct format of the file.
so I saved the video from 0-102400, which is ok and playable, and wanted to get that specific range and somehow append it after the first file to have both a correct file header (less than 1 sec) and that middle part of the video.
first.webm Range: bytes=0-102400 (valid playable file)
middle.webm Range: bytes=307200-614400 (not playable file)
I tried to merge them using this command recommended by this answer
ffmpeg -f concat -i list.txt -c copy merged.webm
logs:
[matroska,webm # 000002143c3e77c0] File ended prematurely00 bitrate=3752.0kbits/s speed=N/A
[matroska,webm # 000002143c429e40] Format matroska,webm detected only with low score of 1, misdetection possible!
[matroska,webm # 000002143c429e40] EBML header parsing failed
[concat # 000002143c3dda80] Impossible to open 'middle.webm'
list.txt: Invalid data found when processing input
frame= 42 fps=0.0 q=-1.0 Lsize= 10kB time=00:00:01.64 bitrate= 48.7kbits/s speed= 231x
video:9kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 8.500000%
generated video only shows the first video (which was already playable before merging) and ends.
I inspired this idea from this answer and don't want to download the complete video. If I can't merge them is it possible and how to write a MIME/header for the middle.webm manually to make it a valid playable video?

Related

HTTP byte range yields a corrupt audio file?

when i open a .m4a or .mp3 file using chrome (or in VLC "open new stream), and skip to a certain time mark, it starts streaming the audio right at that time mark, which means that it downloads a chunk from the audio file starting at that position.
when i check network under chrome dev tools after i click somewhere in the audio player, and copy the cURL request, it contains a range http header, for example:
-H "Range: bytes=26500000-30000000"
when i run that cURL command in the terminal, the output is a corrupt audio file. if i try to convert it using ffmpeg, it logs:
[mov,mp4,m4a,3gp,3g2,mj2 # 00000164d5a3ab40] moov atom not found
the only exception is when i request a byte range starting from 0 (and ending at 300000+) in which case the output file can play.
from what i understand, the headers of the audio file are not downloaded when the byte range is somewhere in the middle or ending of the file.
i tried specifying two ranges, as follows
-H "Range: bytes=0-300000,2000000-4000000"
but the output file is corrupt nevertheless.
how does chrome/vlc deal with this situation, and how can i replicate it? what is the right way to download an audio chunk from a large audio file? i am guessing i would have to make consecutive http requests to build a proper, non-corrupt file, it seems that it is what chrome does.
UPDATE
a "temporary fix" i found to the problem that you might find useful is to use launch VLC through command with a hidden interface, load the audio stream (in this case the audio file url) and transcode the audio to a local file while assigning a start and stop time. an example, with a random podcast:
vlc -Idummy --play-and-exit --sout "#transcode{acodec=s16l,channels=2,samplerate=44100}:std{access=file,mux=wav,dst=C:\audio\output.wav}" --start-time=600 --stop-time=630 "http://traffic.libsyn.com/preview/worldofhardwarestartups/World_of_Hardware_Startups_Podcast_EP01_-_AIR_Ready.mp3"
however, the original issue is still unsolved.

Gstreamer- Duration query error on mp3

I am working on a simple application using Gstreamer on C, that involves playing a song and show some info about it on terminal. Thta info includes the total length of the song in seconds. As usual, I used the function gst_element_query_duration to get this data. The thing is, when I run my program, sometimes it shows the right time on screen, but then I run it again and the total time showed is about 6 seconds less. Because is just a simple trial application, I am using playbin as the general bin for reproduction, so I tried with different file extensions and it seems this only happens with mp3 files. Have anyone ever experienced this? Any ideas on how to fix it?
MP3 has the problem that there is no duration stored inside the file (usually). With constant bitrate files you can simply check the bitrate and the file size, but for variable bitrate files you can only do an approximation based on that. Your problem is probably exactly that.
The only way to know the exact duration of a variable bitrate MP3 file without header information with the duration (see Xing header) is to parse the file until the end and count the exact duration. With playbin you should get the accurate duration at the end of the file.

FFmpeg decoding .mp4 video file

I'm working on a project that needs to open .mp4 file format, read it's frames 1 by 1, decode them and encode them with better type of lossless compression and save them into a file.
Please correct me if i'm wrong with order of doing things, because i'm not 100% sure how this particular thing should be done. From my understanding it should go like this:
1. Open input .mp4 file
2. Find stream info -> find video stream index
3. Copy codec pointer of found video stream index into AVCodecContext type pointer
4. Find decoder -> allocate codec context -> open codec
5. Read frame by frame -> decode the frame -> encode the frame -> save it into a file
So far i encountered couple of problems. For example, if i want to save a frame using av_interleaved_write_frame() function, i can't open input .mp4 file using avformat_open_input() since it's gonna populate filename part of the AVFormatContext structure with input file name and therefore i can't "write" into that file. I've tried different solution using av_guess_format() but when i dump format using dump_format() i get nothing so i can't find stream information about which codec is it using.
So if anyone have any suggestions, i would really appreciate them. Thank you in advance.
See the "detailed description" in the muxing docs. You:
set ctx->oformat using av_guess_format
set ctx->pb using avio_open2
call avformat_new_stream for each stream in the output file. If you're re-encoding, this is by adding each stream of the input file into the output file.
call avformat_write_header
call av_interleaved_write_frame in a loop
call av_write_trailer
close the file (avio_close) and clear up all allocated memory
You can convert a video to a sequence of losses images with:
ffmpeg -i video.mp4 image-%05d.png
and then from a series of images back to a video with:
ffmpeg -i image-%05d.png video.mp4
The functionality is also available via wrappers.
You can see a similar question at: Extracting frames from MP4/FLV?

BATCH file: Scan an imput result for numbers

I'm handling a bat file basically to redirect a streaming media content to VLC, my goal is to pratically automate the whole following steps:
Open the program that bridges the video stream to VLC (DONE)
the program gives a list of available resolutions to use as below:
[cli][info] Found matching plugin ustreamtv for URL
blablabla.com/channel/test
Available streams: 480p+ (best), 480p+_alt_akamai,
480p+_alt_highwinds, mobile_240p (worst)
Now what i need to do is basically find a way to "scan" this information for numbers in order to automate the following string
"C:\Program Files (x86)\Livestreamer\livestreamer.exe"
ublablabla.com/channel/test %quality%"p+_alt_highwinds" > nul
%quality% is there only because I'm currently typing manually whatever resoloution comes out in "Available streams:" to complete the string.
Ther's any way i can filter this result like if there is a 3 digits number before p+_alt_highwinds and automatically complete the string?
I'm sorry if this question looks like a complete mess.

make a video from a subset of images and audio

I want to create a video of three images and three audio files but the duration time of each image should be the time of the corresponding audio file.
Lets say I have three images image_0.png, image_1.png and image_2.png and three audio files audio_0.mp3 (length 10 seconds) , audio_1.mp3 (length 15 seconds), audio_2.mp3 (length 12 seconds).
I want to create a video showing first image_0.png with audio_0.mp3 for 10 seconds, then image_1.png with audio_1.mp3 for 15 seconds and in the end image_2.png with audio_2.mp3 for 12 seconds.
I tried to make this with avconv. I tried different variations of -i commands
avconv -i imageInputFile.png -i audioInputFile.mp3 -c copy output.avi
nothing worked. Indeed, I could make for each image+audio a single avi video, but I failed concatenating all single avi files... Besides this is not the best way I think because of quality loss.
How would you do this? Is this even possible with avconv?
first concatenate all your .mp3 in one single .mp3
then name your .png something like img01.png, img02.png ... imgxx.png
then try:
mencoder 'mf://img*.png' -oac mp3lame -ovc lavc -fps 1 -ofps 25 -vf harddup -audiofile audio.mp3 -o test.avi
obviously replace lavc with your preferred codec and 1 with a reasonable value to fit the frames in your audio track.
some may argue that it's stupid to recompress audio again and I can use -oac copy instead but when converting from multiple sources it can cause issues.
this command creates a 25 fps video stream with 15-26 duplicated frames per second, if you remove -ofps 25 you will avoid duplicate frames but some decoders could hang, especially when seeking

Resources