Mercurial
view mrjunejune/generate_hls_sample.c @ 252:7a7581f040e8
[ui] Add scoped notification component
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 04 Aug 2026 11:57:16 -0700 |
| parents | 543df0fe7168 |
| children |
line wrap: on
line source
#include "third_party/ffmpeg/ffmpeg_cli.h" #include <dirent.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> static int remove_flat_directory(const char *directory) { DIR *entries = opendir(directory); if (!entries) return errno == ENOENT ? 0 : -1; struct dirent *entry; while ((entry = readdir(entries)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; char path[1024]; int length = snprintf(path, sizeof(path), "%s/%s", directory, entry->d_name); if (length < 0 || (size_t)length >= sizeof(path) || unlink(path) != 0) { closedir(entries); return -1; } } closedir(entries); return rmdir(directory); } static int write_master_playlist(const char *directory) { char path[1024]; int length = snprintf(path, sizeof(path), "%s/master.m3u8", directory); if (length < 0 || (size_t)length >= sizeof(path)) return -1; FILE *playlist = fopen(path, "wb"); if (!playlist) return -1; const char *content = "#EXTM3U\n" "#EXT-X-VERSION:7\n" "#EXT-X-STREAM-INF:BANDWIDTH=1200000,AVERAGE-BANDWIDTH=1000000," "CODECS=\"avc1.4d401f,mp4a.40.2\"\n" "h264-stream.m3u8\n" "#EXT-X-STREAM-INF:BANDWIDTH=900000,AVERAGE-BANDWIDTH=750000," "CODECS=\"vp09.00.10.08,opus\"\n" "vp9-stream.m3u8\n"; size_t content_length = strlen(content); int result = fwrite(content, 1, content_length, playlist) == content_length ? 0 : -1; fclose(playlist); return result; } static const char *workspace_path( const char *path, char *buffer, size_t buffer_size) { const char *workspace = getenv("BUILD_WORKSPACE_DIRECTORY"); if (!workspace || path[0] == '/') return path; int length = snprintf(buffer, buffer_size, "%s/%s", workspace, path); return length < 0 || (size_t)length >= buffer_size ? NULL : buffer; } int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "Usage: %s <input.mp4> <output-directory>\n", argv[0]); return 2; } char final_buffer[1024]; const char *final_directory = workspace_path( argv[2], final_buffer, sizeof(final_buffer)); if (!final_directory) { fprintf(stderr, "HLS output path is too long.\n"); return 1; } char stage_template[1100]; int stage_length = snprintf( stage_template, sizeof(stage_template), "%s.stage-XXXXXX", final_directory); if (stage_length < 0 || (size_t)stage_length >= sizeof(stage_template) || !mkdtemp(stage_template)) { fprintf(stderr, "Unable to create the HLS staging directory.\n"); return 1; } Fmp4HlsOpts options = ffmpeg_fmp4_hls_opts_default(); options.codec = FFMPEG_HLS_VP9_OPUS; FfmpegResult result = ffmpeg_video_to_fmp4_hls( argv[1], stage_template, "vp9", &options); if (result == FFMPEG_OK) { options.codec = FFMPEG_HLS_H264_AAC; options.video_bitrate = 1200; options.audio_bitrate = 128; result = ffmpeg_video_to_fmp4_hls( argv[1], stage_template, "h264", &options); } if (result == FFMPEG_OK) { options.use_mpeg_ts = true; result = ffmpeg_video_to_fmp4_hls( argv[1], stage_template, "h264-ts", &options); } if (result != FFMPEG_OK || write_master_playlist(stage_template) != 0) { fprintf(stderr, "%s\n", ffmpeg_last_error()); remove_flat_directory(stage_template); return 1; } char backup_directory[1100]; int backup_length = snprintf( backup_directory, sizeof(backup_directory), "%s.backup", final_directory); if (backup_length < 0 || (size_t)backup_length >= sizeof(backup_directory)) { remove_flat_directory(stage_template); return 1; } remove_flat_directory(backup_directory); bool had_previous = rename(final_directory, backup_directory) == 0; if (!had_previous && errno != ENOENT) { remove_flat_directory(stage_template); return 1; } if (rename(stage_template, final_directory) != 0) { if (had_previous) rename(backup_directory, final_directory); remove_flat_directory(stage_template); return 1; } if (had_previous && remove_flat_directory(backup_directory) != 0) { fprintf(stderr, "Generated HLS sample, but could not remove its backup.\n"); return 1; } printf("Generated fMP4 and MPEG-TS HLS samples from %s in %s\n", argv[1], final_directory); return 0; }