A random pixel on a keyframe. (ffmpeg) - php

Hello folks of SO!
We're trying to do some very small and simple code in PHP to generate a variation of a video, using always the same file.
The script would have to make a small pixel mark, on random or specific frame of the video file, and this would have to be streamed in real time.
Here's some pseudo code to explain my idea:
$frame = $_GET[frame];
$videofile = 'video.avi';
make_random_red_pixel_mark($videofile, $frame);
Does anyone know if this is possible using ffmpeg? As well, it is of extreamly importance for us, to execute this procedure as fast as possible.
A solution that would imply reprocessing the whole video, won't be useful for our purposes. It should be something like a closed caption, or a quick image / overlay filter that could be applied without an entire video reprocessing. As well, we can't put the overlay using Javascript nor any HTML approach, since the actual manipulation has to be on the video file itself.
The quality, and framerate of the original video, should be kept intact. Perhaps some other PHP module or software that could be execute from PHP using an exec()?
Any recommendation?
Thanks in advance!!
Chris C. Russo
More information:
1) It's possible for us to apply this procedure on any frame we want to, so we could use a "keyframe" in order to avoid the decoding and reencoding of an entire GOP.
2) As previously stated, the video stream would have to flow in real time.

This is a hard problem. The FFmpeg overlay video filter requires re-encoding.
When you change ALMOST anything in a video, you will be dealing with re-encoding of the video. This might be an expensive process depending on the video and on the how hurry you are (if you want real-time, you are in a hurry).
A possible solution for this would be something like this:
Open the INPUT video.
Create the OUTPUT video.
Loop over the packets of the INPUT video until you find the frame you want.
Reading the flags of the video packets (AVPacket structure) you can identify the Group of Pictures of this frame.
Ok, you will have to RE-ENCODE only the frames that belong to this group of pictures. Because a GOP always start with a keyframe, you will be able to do that.
After done, go on reading the packets of the INPUT and writing it to the OUTPUT (transmux).
The process of reading a packet from source and write to destination is called transmux and is very very cheap for live streaming. It's basically a plain copy of bytes. No big deal.
"The hard part here is that you will have to manage a POOL of packets until you identify the GOP where your frame is located. Why? Because you will read all packets AND STORE them in a pool (without decode the packets). When you identify it's a GOP, you will write these packets to your OUTPUT and go on to the next GOP. So you will always have the GOP in memory to be flushed (all packets together). When you identify the target frame you wanna modify. I will have to DECODE THE FRAMES from the beginning of the GOP to the end, modify the frame you want and then REENCODE this GOP! Well very hard!"
For arbitrary videos, this process above may result in a visible difference of quality of encoding in the GOP you reencoded. :-(
If you don't know how to open a video, read the packets, write the packets, etc, etc... you will have to know the basics os FFmpeg.
In order to do that, I suggest you to study this example if you don't know anything about:
Demuxing: http://ffmpeg.org/doxygen/trunk/doc_2examples_2demuxing_8c-example.html
Muxing: http://ffmpeg.org/doxygen/trunk/doc_2examples_2muxing_8c-example.html
This example will teach you how to open the video, identify the audio/video streams and loop over the packets, as well as decoding and reencoding.
Hard job. These examples are in C. You can decide make a plugin for PHP or use a PHP wrapper for FFmpeg.
OTHER SOLUTION IS: If you have flexibility of choose frame, try to reencode only keyframes. Because keyframes are complete "bitmaps". You don't need to deal with GOPs. You will decode and reencode only 1 frame.

Related

ID3 Tag while merging MP3s in real time, using PHP and HTTP Partial Content

What we want to do is to add a kind of MP3 preroll to an other MP3 file in real time. That means we have two physical MP3 files on the server which are not merged into one yet, because ffmpeg & Co. take too much time. It has to be in real time to not loose time when someone starts the (web)player. The practical case is to add prerolls to podcast files. What we already did (described below) works, except displaying the correct file duration in audio players.
One of my co-workers did this, so I try to describe as good as possible.
What my coworker already did is telling the header that two files are coming in a row by reading both files and echoing them via PHP. HTTP/1.1 206 Partial Content is used for delivering the "merged" content.
The problem is, that there are still two ID3 Tags from both files and most audio players only read the first one, which occurs wrong duration displays. The only case it works 100% is in VLC after downloading the whole thing. No webplayer, no iTunes etc. can manage the "merged" file duration.
Any idea how to create a "virtual ID3 Tag" in real time and how to remove the existing ones without touching the original files?
There are a lot of inaccurate conclusions you've come to, so let me start by correcting those, which may help you solve the problem.
because ffmpeg & Co. take too much time
FFmpeg can merge these audio streams faster than you can stream to clients for sure. If you're using -codec copy (which you should be in this case), it will handle all the demuxing/muxing for you. And, keep in mind that you can stream directly out of FFmpeg. No need for an intermediary file.
The practical case is to add prerolls to podcast files.
The FFmpeg route is what you want.
What my coworker already did is telling the header that two files are coming in a row by reading both files and echoing them via PHP. HTTP/1.1 206 Partial Content is used for delivering the "merged" content.
That's a bit of a wonky way to do this. You could instead just merge the data and send it directly in a single response.
The problem is, that there are still two ID3 Tags from both files and most audio players only read the first one, which occurs wrong duration displays.
No, the usual ID3 tags don't indicate duration. (There is an extension which does, but this is rarely used.) There is nothing in the bare MP3 stream that indicates duration either. Clients estimate this based on file size and bitrate. The bitrate can change mid-stream, so they usually estimate based on the bitrate of the first couple frames.
Undoubtedly, the problem in your case is incorrect length headers due to the way you're handling this merging, and/or a mismatch of bitrate which causes the length estimate from the player to be wrong.
Any idea how to create a "virtual ID3 Tag" in real time and how to remove the existing ones without touching the original files?
I would absolutely use FFmpeg for this work. If anything, because not all podcasts use MP3. There are plenty of AAC in MP4 podcasts, and a handful of Opus in WebM as well.

splice uploaded video into 1mb chunks in php

Assuming a user has just uploaded a 10mb MP4 video called video.mp4 through a form input with the name video.
Would it be possible to "splice" up the video into 10 1mb chunks, or are there any libraries available which would be able to do this?
This way, when a video is selected to load inside the <video> tag, it will use the first one of those chunks of videos to play first, then load the rest while the other is playing and essentially stack them on the ends of each clip.
I know it seems like a pretty broad question, but I can't seem to find any other post similar to this (or any other solutions for that matter).
Thanks.
You can use https://github.com/PHP-FFMpeg/PHP-FFMpeg which is pretty mature and well documented.
In your case, what you're interested in is the clip method:
$video->filters()->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15));
You shouldn't really need to do this so long as your server supports range requests:
https://en.wikipedia.org/wiki/Byte_serving
This will allow the client, i.e. the browser, to request chunks of the file at a time form the server and start playing back as soon as it had enough to star the video.
If you are concerned about user experience then you probably want to go a bit further and support multiple bit rates and a streaming protocol which support bit rates changes such as HLS or MPEG-DASH. This will allow for different quality video chunks to be survived depending on network conditions.
At this point you are generally better to use a dedicated Video server or video hosting service as the functionality is relatively complex and specialised and its generally easier than re-creating it yourself. Open source streaming server exist such as:
https://gstreamer.freedesktop.org
http://www.videolan.org/vlc/streaming.html

ffmpeg: 1 frame manipulation on demand

Hello folks & friends of SO!
We need to create a small application to take a random frame from a video, and apply some modifications to it, in real time.
This has to be done in real time, and in order to do that, we wouldn't mind to create some initial delay, before the video starts streaming. So let's assume we have a total of 6 seconds of preloading time, in order to:
1) extract a keyframe.
2) create an image with it.
3) manipulate the image.
4) replace the original keyframe with the new one.
The point (3) of the previous algorithm is already solved using GD as a PHP module. However we would need to find a solution for the rest of the procedure in order to accomplish this.
Please if anyone is available to help us with this, feel free to contact me.
Thanks in advance;
Chris C. Russo
This is a pretty complicated problem that cannot be solved by simply replacing the keyframe with a modified image. Following problems (at least) should be addressed for this to work:
Re-encoding all the frames that depend on the keyframe. Otherwise, the video would be corrupt.
File format considerations - The modified keyframe and subsequent frames are likely to have a different size after encoding (compared to the original encoded data). Storing them in the output file is not easy
Timestamp - The timestamp information for these modified frames must be preserved, else there would be audio-video sync issues in the output file.
Given these issues, my recommendation is to perform the image manipulation in the raw video frame, and encode the stream afterwards. Please let me know if I can help clarify.

jPlayer Stream MP3 but prevent from downloading and hotlinking

I am building a site similar to thefuture.fm. DJs are able to upload MP3 files and set if the file only can be streamed or streamed and downloaded.
Visitors to the site don't have to login to listen to music. They should be able to stream/download these MP3 songs depending on the users settings.
I am using the jPlayer to play songs. I have searched all over the web but can't find any solution. Does jPlayer have any facility like prevent downloading of MP3 files? Or is there any way I can prevent this?
It's actually impossible to prevent downloading. You can make it harder for somebody, but he still needs to download all the data to hear the song. So even if you use some encryption to send the data to a flash player you write yourself, the player will have to decrypt it and play the audio. And since you can decompile flash it wouldn't be to hard to find out the algorithm. He could also just record the music again when playing it (similar to the first DVD decrypt tools, who just took a screenshot 30 times/sec to pass million dollar security measurements)
So the goal is to make it harder, not impossible.
Personally I would go for temporary available links in combination with a cookie, so I can still use jplayer and don't have to reinvent the wheel. Also use some obfuscating to make it harder to read the URL.
When somebody request the main URL (where you show your player) generate a unique key and save it in a cookie. The unique key should link to the IP address and request time stored in session.
Now create a link to the music file like playfile.php?file=music.mp3 or whatever. Just make sure that PHP will handle the file request. If you obfuscate this link it will be a little harder to find it.
In playfile.php check for the unique code in the cookie and check if it matches the IP address in session and the request time is less then EG 15 seconds (any longer and music won't play anyway with slow internet connection). If it is, stream the file. If it's not, block it.
Now if somebody would write a program/script to download the music, he can. But if somebody has the knowledge and time to do that, nothing will stop him from downloading it.
This will prevent any normal user from downloading it.
Preventing hotlinking is a bit easier, since in general you'll have a referrer string to check. If this is present then you'll know not to serve the content. Here is a code example.
Preventing downloading on the other hand is much harder - the best approach would be for a Flash application to decrypt data in realtime - if you use a simple encryption scheme, most client hardware should be fast enough. I couldn't find much for this on the web, so I wonder whether you'd have to do some Flash/Flex development yourself: download MP3 data in chunks, apply decryption routines from a library, and send them to some sort of MP3 decoding buffer. I suspect the password would be hard-coded.
Addendum: I've found that in later versions of Flash you can play dynamically generated sounds from a buffer (see here). So, if you're willing to get stuck into some Flash/Flex development, a solution is in sight. I couldn't find anything that accesses low-level MP3 routines, but don't forget that files don't have to be MP3 as transmitted from your server - convert them to whatever your app needs.
What you are searching for can't be achieved with JavaScript solution. If you want javascript to play something, it has to download it and in order to download it, JavaScript needs a URL.
Most common way to tackle this problem is using Adobe Flash and making a player in it. You can make your player stream content (mp3 in your case) without explicitly exposing actual data location to user.
Put the file(s) in a location that isn't accessible from the browser and use PHP to stream them out as a series of chunks using HTTP/1.1 206 Partial Content. Then use a method like this to edit the context menu to add/remove the 'save as'.
Use a session var to eliminate direct linking.
Actually, there is a player that DOES scramble the url and it works pretty good. We used it because of this excellent feature. It is not impossible to download/save the audio, but at least it is not a matter of just opening the inspector and copying the url. It also prevents from sharing to outside sources by URL. So, contrary to the above, it IS possible and it IS available :)
Check the plugin out here:
https://wordpress.org/plugins/mp3-jplayer/

How do I split an OGX (video) file?

I'm trying to make a PHP script that will deliver a given .ogx file based on a seek position (transmited as a parameter to the script). The purpose is to make a HTML5 video player with server-side seeking functions.
I have studied the container format a bit and made the .php script to start delivering data from the first instance of the "OggS" string that occurs before the seek position (given in bytes).
The problem is, even though my new .ogx file starts with the "OggS" string, it is completely unplayable in HTML5, VLC or any other player as long as the seeking position is other than 0.
If I set the seeking position to 0, the script will give me the whole file and that's playable.
So how do I trim the start of an .ogx file while still producing a valid bitstream?
You should take a look at FFMpeg, which is a library that let's you manipulate in different kind of ways video and audio files. http://www.ffmpeg.org/
From their site
FFmpeg is a complete, cross-platform
solution to record, convert and stream
audio and video. It includes
libavcodec - the leading audio/video
codec library.
First of all i should point out that the common extension for the video in the Ogg container is .ogv. The one you are using .ogx is reserved for the executable code within Ogg container, but currently there are no streams that can carry such code (there was an attempt to create the substitute for Flash, but it didn't take off).
Secondly, the very first frame of the theora holds all the metadata about the stream. The reason why players cannot play it is due to this fact. If you intend to allow for such a seeking option you'll need to resend that first frame (you will probably not even need to decode it, just resend it).
So what you are looking for is:
Find the first theora OggS packet, record it.
Seek to the point that you need.
Send the recorded packet.
Skip the data until the next "OggS".
Begin streaming the data as you usually do.
Since your file is likely to contain Vorbis stream as well as Theora, you may want to send its first packet on as well.

Categories