Skip to content
This repository has been archived by the owner on Mar 25, 2019. It is now read-only.

Error when encoding to HLS #31

Closed
jbankston opened this issue Jul 24, 2014 · 15 comments
Closed

Error when encoding to HLS #31

jbankston opened this issue Jul 24, 2014 · 15 comments

Comments

@jbankston
Copy link

When using ffmpeg from the command line the first command works. Since hls encoding creates multiple segments from the video files I am having trouble getting this to work. The code only seems to support a single output. Can this feature be added to the repo?

Command Line
ffmpeg -i LM.mp4 -vb 2500k -minrate 2500k -maxrate 2500k -bufsize 2500k -vf "scale='min(iw,1280)':-1" -s 1280x720 -acodec libfaac -ab 128000 -ar 44100 -ac 2 -vcodec libx264 -sn -r 29.97 -map 0 -f segment -segment_time 10 -segment_list playlist.m3u8 -segment_format mpegts -vbsf h264_mp4toannexb -flags -global_header 720p-%d.ts -threads 0

Preset
I entered this string as a preset in the scheduler.
ffmpeg -i LM.mp4 -vb 2500k -minrate 2500k -maxrate 2500k -bufsize 2500k -vf scale='min(iw,1280)':-1 -s 1280x720 -acodec libfaac -ab 128000 -ar 44100 -ac 2 -vcodec libx264 -sn -r 29.97 -map 0 -f segment -segment_time 10 -segment_list playlist.m3u8 -segment_format mpegts -vbsf h264_mp4toannexb -flags -global_header 720p-%d.ts -threads 0

@tieleman
Copy link
Contributor

This question comes by a lot. We are considering a way to do this, but currently it is not supported. Why? codem-transcode is built with the philosophy that one input file goes in and one input files comes out. This keeps the system easily scalable to convert lots and lots of files. For example: you can just add a second transcoder and your capacity doubles when using a scheduler to distribute jobs.

After we built codem-transcode, ffmpeg added HLS and segment muxers to create multiple outputs from a single file. These muxers break away from the single file in, single file out pattern and are therefore currently not supported. The problem is we can't write reliable code that can understand/predict which files ffmpeg is going to generate, without basically implementing the same logic that the ffmpeg muxers use, which makes it impossible to do any post-processing on these files (like copying/moving them to a different, final location).

The way we have used codem to do HLS (and MPEG-DASH) is to create separate jobs for the different bit rates you want to generate: one bit rate equals one job. Then afterwards, we hook into the job callback to determine which jobs have finished and then do a post-processing packaging step (using for example GPAC MP4Box, or the Apple HLS segmenter).

That way, you can still scale out lots of your jobs over different machines and create the HLS segments once all jobs have completed. Furthermore, you separate the encoding and packaging steps, so the encoder doesn't need to know about your intended delivery system (HLS, MPEG-DASH, Smooth Streaming) and the packager doesn't need to know about the encoder.

It is unfortunately not just a case of simply adding some code (without resorting to a hack), it requires that we reconsider the basic way codem currently functions. We are thinking about it, but I don't think it will be any time soon. Sorry.

@jbankston
Copy link
Author

Tieleman,

I appreciate the quick response. I may need to clarify what I am asking for. I am currently encoding 1 video at one bitrate and it outputs many segmented *.ts files. I can declare a destination file and it currently just creates one large .ts file instead of the segments. Thanks again.

@tieleman
Copy link
Contributor

Ok, try removing 720p-%d.ts from the preset and pass that as the destination file. It might work, but I can't guarantee it.

Also, I don't know if it's a typo, but don't specify ffmpeg -i LM.mp4 in the preset in the scheduler. It will already automatically call ffmpeg and use your supplied input file as input.

@jbankston
Copy link
Author

That didnt work. We will take your advice and do the processing in post. Thanks again!

@tieleman
Copy link
Contributor

Just to clear up, I found out why it doesn't work. Codem-transcode always uses a single tmp file. After transcoding is complete, it tries to move the tmp file to the final destination. Currently this is not something that can be disabled, that's why the segment template option is not working. Again, that is due to the single input, single output design decision when we started the project. I hope we can make that more flexible in the future, so thanks for bringing it to my attention once more. ;)

@deedos
Copy link

deedos commented Aug 15, 2014

@tieleman .. which apple hls segmenter are you using for the post-packaging ? many thanks in advance

@jbankston
Copy link
Author

@deedos,
here is a quick script we have been using to transcode ts files into segments with a manifest.

ORIG_FILE_DIR=/tmp/processed
POST_FILE_DIR=/tmp/segmented

for i in ls $ORIG_FILE_DIR/*.ts; do
ffmpeg $POST_FILE_DIR/$i -map 0 -f segment -segment_time 10 -segment_list playlist-%d.m3u8 -segment_format mpegts -vbsf h264_mp4toannexb -flags -global_header ffprobe FILENAME 2>&1 | grep Video | awk '{print $10}' | tr -d , -threads 0
done

@deedos
Copy link

deedos commented Aug 15, 2014

@jbankston many thanks for sharing. Do you handle multiple bitrate hls as well ?

abraços

@jbankston
Copy link
Author

@deedos,
Np. Not at the moment but it shouldn't be too difficult to modify the script and add support. If I have time this weekend I will try to update the script.

@cutalion
Copy link
Contributor

Hi there,

@tieleman, you said about philosophy of codem-transcode. One file in, one out.
Using a temporary file and coping it to destination folder, etc.
I like this. It realy makes things easier.

However, I noticed, that codem-transcode can generate many thumbnails as a part of a single job.
And there is no problem with this.

I'm thinking about adding another options - hls_options or segmented_output_options.
I hope I can add another post processing to the didFinish method or somewhere at final step.

At this additional step I'd like to call ffmpeg on ready destination_file.
Command may look something like this:

ffmpeg -i input.mp4 -codec copy -map 0 -f segment \
-vbsf h264_mp4toannexb -flags -global_header -segment_format mpegts \
-segment_list output.m3u8 -segment_time 10 output-%03d.ts

Without re-encoding file again. Just converting to proper mpegts format.
(It is pretty fast in my tests).

What do you think about all this? Would you accept a PR with these changes?

Thanks,
Alex

@tieleman
Copy link
Contributor

Hi Alex,

Yes, we added the higher-level thumbnails option because it was requested by a customer. I'd accept something like you're suggesting of course, as long as it doesn't interfere with the regular way Codem works. So adding it as an additional option seems fine. In the future I'd like to move to a more modular way of doing things, e.g. transcoding, segmenting/packaging, delivery, etc., but I don't see any problem in augmenting the current functionality as long as it doesn't cause issues with being backwards compatible.

How would you see the segment-options? What would be configurable for the user?

Thanks!

@cutalion
Copy link
Contributor

Hi Sjoerd,

Since I decided to make it as a post-processing, I think there will be only one option - segment_time. User will create new preset with encoding settings, which should prepare file to segmentation without re-encoding. Not all files can be segmented with -codec copy.

I understand, that it would be better to make it more modular. And there is a dependency between
encoding settings and segmenting. But it probably not so bad for the "post-processing" options, as it would be for different jobs.

So segment_options would look like {segment_time: 10}. This is all that user will change.

There are some internal changes - we need new text column in the database to store paths to segments and playlist. Hm.. 2 columns. Is there any docs about migrations? How to run them?

I'm also use codem-schedule. I, probably, have to update it as well.

Thanks

@cutalion
Copy link
Contributor

@tieleman I'm wondering why thumbnails are not stored in the DB on codem-schedule side?
Is there any reason for that?
I'd like to store paths to segments and playlist on scheduler in order to retrieve them later in main app.

@tieleman
Copy link
Contributor

The migrations are standard from Sequelize (see http://sequelizejs.com/docs/1.7.8/migrations), they get run whenever the transcoder starts, so you can add them to the migrations directory. As for why the thumbnails aren't added to the scheduler I'm not sure. I'm adding @bartzon as well, he wrote most of the scheduler.

@tieleman tieleman reopened this Aug 21, 2014
cutalion added a commit to cutalion/codem-transcode that referenced this issue Aug 22, 2014
Added `segments_options` to job input options, which only can contain
a `segment_time` time parameter so far.

This feature added as a "post-processing" action and requires
`encoder_options` to be set. They also should prepare file to be
"segmentable". Not all files can be segmented without re-encoding.

This action applies on ready `destination_file`.
It generates playlist named "destination_file_basename.m3u8" and a set
of segments in a mpegts format named "destination_file_basename-%06d.ts"

Also method `Job#finalize` refactored a bit. Moved few guard clauses to
the top instead of 3-levels if-else conditions.

Related to madebyhiro#31
cutalion added a commit to cutalion/codem-transcode that referenced this issue Aug 22, 2014
Added `segments_options` to job input options, which only can contain
a `segment_time` time parameter so far.

Also added `playlist` and `segments_options` columns to the Job model and API
ouput.

This feature adds as a "post-processing" action and requires
`encoder_options` to be set. They also should prepare file to be
"segmentable". Not all files can be segmented without re-encoding.

Segmenting applies on ready `destination_file`.
It generates playlist named "destination_file_basename.m3u8" and a set
of segments in a mpegts format named "destination_file_basename-%06d.ts"

Also method `Job#finalize` refactored a bit. Moved few guard clauses to
the top instead of 3-levels if-else conditions.

Related to madebyhiro#31
@tieleman
Copy link
Contributor

tieleman commented Sep 8, 2014

Closed with #34

@tieleman tieleman closed this as completed Sep 8, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants