What is the best way to calculate the length of flv file using php with out external dependencies like ffmpege because client site run on shared hosting,
itry http://code.google.com/p/flv4php/, but it extract metadata and not all video contain meta data ?
There's a not too complicated way to do that.
FLV files have a specific data structure which allow them to be parsed in reverse order, assuming the file is well-formed.
Just fopen the file and seek 4 bytes before the end of the file.
You will get a big endian 32 bit value that represents the size of the tag just before these bytes (FLV files are made of tags). You can use the unpack function with the 'N' format specification.
Then, you can seek back to the number of bytes that you just found, leading you to the start of the last tag in the file.
The tag contains the following fields:
one byte signaling the type of the tag
a big endian 24 bit integer representing the body length for this tag (should be the value you found before, minus 11... if not, then something is wrong)
a big endian 24 bit integer representing the tag's timestamp in the file, in milliseconds, plus a 8 bit integer extending the timestamp to 32 bits.
So all you have to do is then skip the first 32 bits, and unpack('N', ...) the timestamp value you read.
As FLV tag duration is usually very short, it should give a quite accurate duration for the file.
Here is some sample code:
$flv = fopen("flvfile.flv", "rb");
fseek($flv, -4, SEEK_END);
$arr = unpack('N', fread($flv, 4));
$last_tag_offset = $arr[1];
fseek($flv, -($last_tag_offset + 4), SEEK_END);
fseek($flv, 4, SEEK_CUR);
$t0 = fread($flv, 3);
$t1 = fread($flv, 1);
$arr = unpack('N', $t1 . $t0);
$milliseconds_duration = $arr[1];
The two last fseek can be factorized, but I left them both for clarity.
Edit: Fixed the code after some testing
The calculation to get the duration of a movie is roughly this:
size of file in bytes / (bitrate in kilobits per second / 8)
Related
I am scraping an RSS Feed which includes <enclosure> elements for audio files. According to the spec, the length is given in bytes.
<enclosure url="https://www.w3schools.com/media/audio-file.m4a" length="67960845" type="audio/x-m4a" />
I need to convert this length into an actual measurable time (i.e. hours, minutes, seconds). This would require knowing the bitrate (I believe), which I happen to have! The RSS feed comes from Anchor and according to Anchor, they sample their audio in stereo at 44.1 kHz, 128 kbit/s CBR.
I know the provided example length="67960845" converts to 71 minutes. I tried to reverse engineer it but I can't really find a good formula in order to reliably convert this like:
<?php
$length = 67960845;
$seconds = $length / ????;
?>
This request is in PHP but could apply to any language scraping an RSS feed.
If you convert the length to bits you can then divide it by the bitrate and then get the number of seconds:
(67960845*8)/128/1000/60 = 70.792546875
So...
$length = 67960845;
$bitrate_kbps = 128;
$seconds = ceil(($length * 8) / $bitrate_kbps / 1000 / 60);
Does this work for you?
I'm trying to use PHP to parse a custom gzip archive file format that was created in Delphi (not my code!). The format is basically:
4-byte integer: count of files in archive
for each compressed file:
4-byte integer: filename length [n]
[n] bytes: filename
4-byte integer: uncompressed file length [m]
[????] bytes: gzipped content
I can read the file and actually decode the first compressed file correctly by using zlib_decode() with a max uncompressed length of [m] bytes on the remainder of the file after I know the length ([m]), but then I'm stuck because I don't know how far into the substring I should go to find the next filename -- zlib_decode() doesn't return the number of compressed bytes that it processed before stopping. Since this is a custom format, it doesn't seem like I can use the normal gzopen()/gzread() functions because the entire file isn't compressed (I tried, it doesn't work).
This code works in Delphi because apparently you can pass a file handle back and forth between normal file reading functions and the System.ZLib decoding functions -- you can read [m] uncompressed bytes and the pointer will remain at the last compressed byte -- but PHP doesn't seem to support switching between read-as-normal and read-as-gzip on the fly that way.
Am I missing an obvious way in PHP to deal with a mixed-content file format like this, where metadata and compressed data are stacked together this way? Or am I out of luck without knowing the compressed data length?
A dirty workaround is to recompress the content of each file as I am able to parse it, use that to calculate the compressed length, and adjust the file pointer in the original file manually as follows:
$current_pos = ftell($handle);
$skip_length = strlen(gzencode($uncompressed_text,9,FORCE_DEFLATE));
fseek($handle, $skip_length+$current_pos);
This works, but feels very hack-ish. I'd still be open to any better approaches.
EDIT:
Just a note that this eventually failed. However, I was fortunate enough to know in advance the list of expected filenames and I was able to do the following (more reliable since zlib_decode() will decode as much as it can and discard the rest anyway):
foreach ($filenames as $thisFilename) {
$thisPos = strpos($rawData, $thisFilename);
$gzresult = zlib_decode(substr($rawData, $thisPos + strlen($table) + 8)); // skip 8 bytes for filename size and uncompressed data size, which are useless info.
}
Using php, how can I read a zip file and get its bytes, for example something like
$contents = file_get_contents('myzipfile.zip');
echo $contents;
// outputs: 504b 0304 1400 0000 0800 1bae 2f46 20e0
Thank you!
file_get_contents gets the raw bytes, your echo outputs those raw bytes. If you expect to output a hexadecimal notation of the raw byte contents instead, use bin2hex:
echo bin2hex($contents);
If you want that arbitrarily grouped with a space every two bytes, you can do something along these lines:
echo join(' ', str_split(bin2hex($contents), 4));
(Note that this is all rather inefficient, modifying the entire, possibly many megabyte large file in memory. I'm expecting this is just for debugging purposes, so won't go out of my way to write super efficient code.)
file_get_contents() will return the exact contents of the file, so the format depends on the file type.
If you are looking for the byte size of the file you can get any available file information with the core SPL library's fileInfo class:
$info = new SplFileInfo('myzipfile.zip');
$bytes = $info->getSize();
This question already has answers here:
Measure string size in Bytes in php
(5 answers)
Closed 8 years ago.
I have an encrypted image and before saving it I would like to know how much space it takes up. I can get the number of characters via strlen($img) or via mb_strlen($img) but I would like to get a number like 16KiB (or KB).
I then save the string into a MySQL database in blob format, where I can see the size of it using PhpMyAdmin.
EDIT
If I use strlen to get the byte size of the string (which I want) I get a different value from the byte size displayed in my MySQL database (where the string is not saved as a char but as a blog, meaning binary). How can this be? And how can I find out how large the binary size will be when I save the string in the database.
I save the string simply with the MySQL command
INSERT INTO table (content, bla) VALUES ($string, bla);
(not fully correct but for example purpose – this works when correct)
Now when I look inside my database it displays me a size e.g 315 KB but when I take $string and do strlen on it, it returns something like 240000 (Not the same in bits as in KB)
I will investigate my self...
This does essentially the same thing as Dany's answer, but a little more compact.
function human_filesize($bytes, $decimals = 2) {
$size = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . #$size[$factor];
}
echo human_filesize(filesize($filename));
Source: http://jeffreysambells.com/2012/10/25/human-readable-filesize-php
i am working on a php-script which encodes given text and hides that in an Image using LSB. But the encoded text is a Byte Array (text encrypted using mcrypt with rijndael-256 and then unpacked with unpack("C*", $encryptedText);) i have tp add the array-size at the beginning of the Array. if i would not do this, reading the Bytes from the Image again would be terrible later on, because the script would not know where to stop reading. I added size Information at the beginning of the Array using These lines of code:
$size = count($byteArray);
array_unshift($byteArray, $size >> 24, ($size & 0xff0000) >> 16, ($size & 0xff00) >> 8, $size & 0xff);
so the size is added in integer Format (4bytes), but now every Image created would have the characteristics that the first hidden Bytes start mostly with Zeros, besause $size is mostly in the range of 60000 or lower. is there any way i can encode size or Change other parts of the program so that it works and the beginning of the bytearry is not nearly the same every time?
Instead of always having the first 4 bytes encoding how long your message is, you can use the last two bits from the first byte to encode how many bytes you need to read for $size. Say, 00 = 1, 01 = 2, 10 = 3 and 11 = 4. For example, if $size is small enough to be expressed with just two bytes, the first few bytes will read as follow:
First byte: xxxxxx01
Second and third bytes: $size
Fourth byte and onward: ByteArray...
You can spice things up further by using a randomised embedding method. You can use a pseudorandom number generator, or chaotic maps, such as the Logistic Map, or Tent Map. The seed or initial condition parameters will be required by the receipt to decipher in what order to read the bytes to extract the message. For example, consider 5 bytes to embed data and 5 numbers generated between 0 and 1.
(0.2843, 0.5643, 0.0904, 0.4308, 0.9866)
Sorting the numbers in ascending order gives you the following order, which you can use to embed your secret:
(3, 1, 4, 2, 5)