OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How to get a fragment of an mp4 video file from the middle, but keep the file metadata ussing nodejs aws

  • Thread starter Thread starter turaiev
  • Start date Start date
T

turaiev

Guest
Code:
export async function* initiateObjectStream(
  Key: string,
  start: number,
  end: number,
): AsyncGenerator<any, any, unknown> {
  const streamRange = `bytes=${start}-${end}`;

  const getObjectCommand = new GetObjectCommand({
    Bucket: bucket,
    Key,
    Range: streamRange,
  });

  const { Body: chunks} = await s3Client.send(getObjectCommand);


  for await (const chunk of chunks) {
    yield chunk;
  }

}

I'm using this function to get an mp4 video file that will be later streamed to an HTML video player

When the start = 0 parameter is passed to the function argument, everything works. Because the chunks of the video file are broadcast from the beginning. And the first chunks of the video have the necessary metadata that indicate to the HTML Video player that this is a video and it should be displayed

When I want to display the video not from the beginning, but from the middle, the start value is different. B from AWS, I receive a video fragment that no longer has the first chunks with metadata. Because of this, the HTML video player closes the stream after receiving the first 3 chunks in which it expects metadata

how can I get the first chunks with metadata of my file through aws and glue them with the chunks of the desired fragment?

or how can I create the first metadata chunks myself? And what values should I specify in the metadata?




I was trying to add metadata by another chunks, but it didnt help me

Code:
export async function* initiateObjectStream(
  Key: string,
  start: number,
  end: number,
): AsyncGenerator<any, any, unknown> {
  const streamRange = `bytes=${start}-${end}`;

  const getObjectCommand = new GetObjectCommand({
    Bucket: bucket,
    Key,
    Range: streamRange,
  });

  const { Body: chunks } = await s3Client.send(getObjectCommand);

  //@ts-ignore
  const passThroughStream = new PassThrough();

  const ftypChunk = Buffer.alloc(28);
  ftypChunk.writeUInt32BE(28, 0);
  ftypChunk.write('ftyp', 4);
  ftypChunk.write('mmp4', 8);
  ftypChunk.write('isom', 12);
  ftypChunk.write('iso2', 16);
  ftypChunk.write('mp41', 20);
  ftypChunk.write('mp42', 24);

  const mdatChunk1 = Buffer.alloc(8);
  mdatChunk1.writeUInt32BE(8, 0);
  mdatChunk1.write('mdat', 4);

  const mdatChunk2Size = 303739;
  const mdatChunk2 = Buffer.alloc(8 + mdatChunk2Size, 0x01); // I dont know what I need to do on this part
  mdatChunk2.writeUInt32BE(8 + mdatChunk2Size, 0);
  mdatChunk2.write('mdat', 4);

  const moovChunkSize = 6202;
  const moovChunk = Buffer.alloc(8 + moovChunkSize, 0x02); // I dont know what I need to do on this part
  moovChunk.writeUInt32BE(8 + moovChunkSize, 0);
  moovChunk.write('moov', 4);

  passThroughStream.write(ftypChunk);
  passThroughStream.write(mdatChunk1);
  passThroughStream.write(mdatChunk2);
  passThroughStream.write(moovChunk);
  passThroughStream.end();

  for await (const chunk of passThroughStream) {
    yield chunk;
  }

  //@ts-ignore
  for await (const chunk of chunks) {
    yield chunk;
  }
}

I also tried to use this library in such a format to share method chunks with chunks of the video fragment itself, but that didn't help either.

Code:
const ffmpegStream = ffmpeg()
    .input(chunks)
    .format('mp4')
    .addOutputOptions(
      '-movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov',
    )
    .on('error', function (err) {
      console.log('An error occurred: ' + err.message);
    })
    .on('end', function () {
      console.log('Processing finished !');
    });

  const ffstream = ffmpegStream.pipe().on('data', function (chunk) {
    console.log('ffmpeg just wrote ' + chunk.length + ' bytes');
  });
<pre><code>export async function* initiateObjectStream(
Key: string,
start: number,
end: number,
): AsyncGenerator<any, any, unknown> {
const streamRange = `bytes=${start}-${end}`;

const getObjectCommand = new GetObjectCommand({
Bucket: bucket,
Key,
Range: streamRange,
});

const { Body: chunks} = await s3Client.send(getObjectCommand);


for await (const chunk of chunks) {
yield chunk;
}

}
</code></pre>
<p>I'm using this function to get an mp4 video file that will be later streamed to an HTML video player</p>
<p>When the start = 0 parameter is passed to the function argument, everything works. Because the chunks of the video file are broadcast from the beginning. And the first chunks of the video have the necessary metadata that indicate to the HTML Video player that this is a video and it should be displayed</p>
<p>When I want to display the video not from the beginning, but from the middle, the start value is different. B from AWS, I receive a video fragment that no longer has the first chunks with metadata. Because of this, the HTML video player closes the stream after receiving the first 3 chunks in which it expects metadata</p>
<p><strong>how can I get the first chunks with metadata of my file through aws and glue them with the chunks of the desired fragment?</strong></p>
<p><strong>or how can I create the first metadata chunks myself? And what values should I specify in the metadata?</strong></p>
<hr />
<p>I was trying to add metadata by another chunks, but it didnt help me</p>
<pre class="lang-js prettyprint-override"><code>export async function* initiateObjectStream(
Key: string,
start: number,
end: number,
): AsyncGenerator<any, any, unknown> {
const streamRange = `bytes=${start}-${end}`;

const getObjectCommand = new GetObjectCommand({
Bucket: bucket,
Key,
Range: streamRange,
});

const { Body: chunks } = await s3Client.send(getObjectCommand);

//@ts-ignore
const passThroughStream = new PassThrough();

const ftypChunk = Buffer.alloc(28);
ftypChunk.writeUInt32BE(28, 0);
ftypChunk.write('ftyp', 4);
ftypChunk.write('mmp4', 8);
ftypChunk.write('isom', 12);
ftypChunk.write('iso2', 16);
ftypChunk.write('mp41', 20);
ftypChunk.write('mp42', 24);

const mdatChunk1 = Buffer.alloc(8);
mdatChunk1.writeUInt32BE(8, 0);
mdatChunk1.write('mdat', 4);

const mdatChunk2Size = 303739;
const mdatChunk2 = Buffer.alloc(8 + mdatChunk2Size, 0x01); // I dont know what I need to do on this part
mdatChunk2.writeUInt32BE(8 + mdatChunk2Size, 0);
mdatChunk2.write('mdat', 4);

const moovChunkSize = 6202;
const moovChunk = Buffer.alloc(8 + moovChunkSize, 0x02); // I dont know what I need to do on this part
moovChunk.writeUInt32BE(8 + moovChunkSize, 0);
moovChunk.write('moov', 4);

passThroughStream.write(ftypChunk);
passThroughStream.write(mdatChunk1);
passThroughStream.write(mdatChunk2);
passThroughStream.write(moovChunk);
passThroughStream.end();

for await (const chunk of passThroughStream) {
yield chunk;
}

//@ts-ignore
for await (const chunk of chunks) {
yield chunk;
}
}
</code></pre>
<p>I also tried to use this library in such a format to share method chunks with chunks of the video fragment itself, but that didn't help either.</p>
<pre><code>const ffmpegStream = ffmpeg()
.input(chunks)
.format('mp4')
.addOutputOptions(
'-movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov',
)
.on('error', function (err) {
console.log('An error occurred: ' + err.message);
})
.on('end', function () {
console.log('Processing finished !');
});

const ffstream = ffmpegStream.pipe().on('data', function (chunk) {
console.log('ffmpeg just wrote ' + chunk.length + ' bytes');
});
</code></pre>
Continue reading...
 

Latest posts

Top