My objective is to take a twitch video stream and generate an image sequence from it without having to create an intermediary file. I found out that ffmpeg can take a video and turn it into a video and turn it into an image sequence. The ffmpeg website says that it's input option can take network streams, although I really can't find any clear documentation for it. I've searched through Stack Overflow and I haven't found any answers either.
I've tried adding the link to the stream:
ffmpeg -i www.twitch.tv/channelName
But the program either stated the error "No such file or directory":
or caused a segmentation fault when adding https to the link.
I'm also using streamlink and used that with ffmpeg in a python script to try the streaming url:
import streamlink
import subprocess
streams = streamlink.streams("http://twitch.tv/channelName")
stream = streams["worst"]
fd = stream.open()
url = fd.writer.stream.url
fd.close()
subprocess.run(['/path/to/ffmpeg', '-i', url], shell=True)
But that is producing the same error as the website URL. I'm pretty new to ffmpeg and streamlink so I'm not sure what I'm doing wrong. Is there a way for me to add a twitch stream to the input for ffmpeg?
I've figured it out. Ffmpeg won't pull the files that are online for you, you have to pull them yourself, this can be done by using call GET on the stream url which returns a file containing addresses of .ts files, curl can be used to download these files on your drive. Combine this with my image sequencing goal the process looks like this on python:
import streamlink
import subprocess
import requests
if __name__ == "__main__":
streams = streamlink.streams("http://twitch.tv/twitchplayspokemon")
stream = streams["worst"]
fd = stream.open()
url = fd.writer.stream.url
fd.close()
res = requests.get(url)
tsFiles = list(filter(lambda line: line.startswith('http'), res.text.splitlines()))
print(tsFiles)
for i, ts in enumerate(tsFiles):
vid = 'vid{}.ts'.format(i)
process = subprocess.run(['curl', ts, '-o', vid])
process = subprocess.run(['ffmpeg', '-i', vid, '-vf', 'fps=1', 'out{}_%d.png'.format(i)])
It's not a perfect answer, you still have to create the intermediary video files which I was hoping to avoid. Maybe there's a better and faster answer, but this will suffice.
Related
My problem basically comes from me having 2 different streams for videoplayback and having to mux them realtime in memory. One for video, and another for audio.
My goal is to create a proxy which can mux 2 different webm streams from their URLs, while supporting range requests (requires knowing the encoded file size). Would this be possible?
This is how I mux the audio and video streams manually using ffmpeg:
ffmpeg -i video.webm -i audio.webm -c copy output.webm
But, this requires me to download the video fully to process it, which I don't want to do unfortunately.
Thanks in advance!
If you are looking for this to work in go you can look into
github.com/at-wat/ebml-go/webm
This provides a BlockWriter interface to write to webm file using buffers; You can see the test file to checkout how to use it
https://github.com/at-wat/ebml-go
Checkout ffmpeg pipes.
Also since you have tagged go - i'm assuming you will use os/exec - in which case also checkout Cmd.ExtraFiles. This lets you use additional pipes(files) beyond just the standard 0, 1 and 2.
So let's say you have a stream for video and one for audio piping to 3 and 4 respectively. The ffmpeg bit of your command becomes:
ffmpeg -i pipe:3 -i pipe:4 -c copy output.webm
How to transfer metadata using FFMPEG or other tools with CMD ?
I'm trying to encode video/audio and since they already have metadata inside obviously i want to preserve them into my new file
btw since i'm using mediamonkey as main player, there's also some Custom metadata. this is the one who wont transfer
for Video output file using mp4/mkv (using x264)
for Audio output file using m4a (using neroAac)
Thank You!
ps. which container is best for neroAac and x264? since i can't seem to edit mkv metadata (when i remove from mediamonkey playlist, they're all gone), mp4 is fine though and i can't seem to play AAC, although it's fine when muxed into video
Copy all custom and global metadata tag information using the following command:
ffmpeg <inputfile> -movflags use_metadata_tags -c copy <outputfile>
I have a directory which contain some files,I loop around this files and stream them using ffmpeg to ffserver,the problem is when song is over,the client stop receiving the stream.VLC and jwplayer have this problem-which I tested-(although I can fix this problem in jwplayer by adding repeat: true option but I don't think it's such a good idea).
what I need is an option or some trick in ffserver which keep connection alive(at least for a while) so that if a song is over,the next song start automatically(it take 1 second to switch songs),maybe ffserver have a timeout option ?
I ended up using concat for streaming files without breaking connection
the easiest way would be to create a file,name it file_paths.txt and add paths to file like this :
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
and then in your ffmpeg command do something like this :
ffmpeg -re -f concat -i file_paths.txt http:/ip:8090/feed1.ffm
this works really well,although all files must have the same codec and format
for more information and see how to use concat for different formats see this
The Situation:
I'm using ffmpeg (via .net) to save video files. I can get the output from ffmpeg but I dont know how can I customize the output to have better result.
My Problem:
My problem is, there is no certain difference between successful and failed operation.
last line of success:
video:1006kB audio:134kB subtitle:0 global headers:0kB muxing overhead 0.943510%
last lines from fails
c:\x\test-9-8/30/2012-9:29:56-AM.mp4: Invalid argument
rtmp://cdn.tv/cdn-live39/definst/stream01: Unknown error occurred
My Question:
Is there an option (or command line parameter) to add some sort of return code (200: success, 500: error, etc)
Thanks!
PS: I saw this topic How to tell if ffmpeg errored? but there is no number before/after last line. I think the last version doesnt have number anymore.
I know this is very old but as i came across and found no other reliable answer and after some more testing:
The suggestion with checking for return of 0 is in general a good advice - but does not help in all cases. The other idea with checking if the file exists is also good - but again - does not help in all cases.
For example when the input file is a mp3 file that has an embedded cover - then ffmpeg does (in my tests) use this image and extracts that one as an (unusable) video file.
What i do now is to have debug level output and parse it for the number of muxed packets.
ffmpeg -i "wildlife.mp4" -c:v copy -an -sn "out.mp4" -y -loglevel debug 2> wildlife.txt
With a regex i search for this text:
Output stream .+ (video): [0-9][0-9]+ packets muxed \([0-9][0-9]+ bytes\)
(this assumes that every video has more than 9 packets - could of course be optimized for really short videos).
Of course for RTMP or other settings the output may differ but i think to parse the full output stream is the only option.
You could just check the exit code returned by ffmpeg. It should return 0 on success, anything else means it failed.
You can run ffmpeg in -v error mode and have it return errors into a text file, see here: https://superuser.com/questions/100288/how-can-i-check-the-integrity-of-a-video-file-avi-mpeg-mp4 You can combine this with encoding without the null output but you will only be able to read the results from the text file.
Or you can have an additional script that will follow-up on the errors. Here is a Python example, which checks for file integrity, notice the if stdout clause. This will basically re-check encoded file if you need to see normal output first.
Solution 1:
import subprocess
import os
import sys
import re
def check_video(files):
if type(files) == str:
files = [files]
for file in files:
print(f"Checking {file}...")
command_line = f'ffmpeg -v error -i "{file}" -map 0:v -map 0:a? -vcodec copy -acodec copy -f null -'
base_name = os.path.splitext(file)[0]
extension = os.path.splitext(file)[1]
process = subprocess.Popen(command_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = process.communicate()
return_code = process.returncode
pid = process.pid
print(f"Base: {base_name}")
print(f"Extension: {extension}")
print(f"RC: {return_code}")
if stdout:
allowed_errs = ["invalid as first byte of an EBML number"]
stdout_detect = stdout.decode().split("\n")
for error in allowed_errs:
if error not in stdout_detect[0] or len(stdout_detect) > 2:
print(f"Errors!")
print(os.path.splitext(file)[1])
os.rename(file, f"{file}.error")
with open(f"{file}.error.log", "w") as errfile:
if stdout:
errfile.write(stdout.decode())
if stderr:
errfile.write(stderr.decode())
else:
print("Minor problems detected.")
else:
print("File OK.")
process.wait()
if __name__ == "__main__":
files = sys.argv[1:]
# files = ["a.mkv"]
check_video(files)
Solution 2:
with subprocess.Popen(command_line,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True) as self.process:
for line in self.process.stdout:
print(line, end='')
return_code = self.process.wait()
From here, you can do whatever you like with each line, like checking for error keywords in them. I think ffmpeg has some standard of error reporting (https://ffmpeg.org/doxygen/trunk/group__lavu__error.html). With this solution, output will be displayed to you same as with directly running ffmpeg. Source: https://stackoverflow.com/a/4417735/1793606. Tested with Python 3.10
Solution 3:
Also, you can set err_detect for ffmpeg itself, that should reflect in the return code
I am trying to use avs2yuv to pipe avs output to ffmpeg for further conversion.
My video file is called "sample.avi" (No sound, just video)
My audio file is called "sample.wav"
My avs file(s) is called sample.avs, and looks like this:
V = AviSource("sample.avi")
A = WavSource("sample.wav")
AudioDub(V ,A)
or
V = DirectShowSource("sample.avi")
A = DirectShowSource("sample.wav")
AudioDub(V ,A)
Here is how I pipe:
avs2yuv sample.avs - | ffmpeg -y -f yuv4mpegpipe -i - output.mp4
Now here is the PROBLEM: No matter what files I try as an input, there is NO SOUND in my output. I do not understand what I am doing wrong, and why my audio does not make it to the output. If anyone has experience with avisynth and avs2yuv, your help would be GREATLY appreciated.
Thank you!
I would try to play your avs file with ffplay in order to check your avs file.
And you can also try to build some GRaph with GraphEdit in order to do something like that
A = DirectShowSource("sample_audio.grf", video=false)
V = DirectShowSource("sample_video.grf", audio=false)
AudioDub(V ,A)
With DirectShow you can add several parameter like fps, frame-count etc... sometime it helps.
Good Luck
As per this link:
Avs2YUV is a command-line program, intended for use under Wine, to
interface between Avisynth and Linux-based video tools.
avs2yuv.exe only handles the video stream which it output in a YUV color-space. It is that simple: the audio stream is ignored.
Here are some ways to process both audio and video streaams in .avs. These methods work in Linux using wine, and do of course work in Windows:
Encode in Avidemux via AvsProxy (AvsProxy ships with Avidemux)
Use VirutalDub as the encoder gui
otherwise encode the audio seperately, then mux in the video in a seperate step.
I believe avs2pipe can handle both video and audio streams fron a .avs, but I haven't tried it yet. Here is a link to some info about avs2pipe
Summary: Using avs2yuv mainly makes sense in a Linux/Unix environment.
Try makeAVIS.exe from the ffdshow package:
wine makeavis.exe -p -i example.avs -a output.wav