{"id":15500053,"url":"https://github.com/mint-dewit/media-conformer","last_synced_at":"2025-04-22T22:43:36.640Z","repository":{"id":37188177,"uuid":"282395159","full_name":"mint-dewit/media-conformer","owner":"mint-dewit","description":"A drag and drop interface to ffmpeg encoding","archived":false,"fork":false,"pushed_at":"2022-12-13T09:22:01.000Z","size":1936,"stargazers_count":11,"open_issues_count":25,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-17T14:36:44.216Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mint-dewit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-25T07:35:25.000Z","updated_at":"2024-10-02T09:33:09.000Z","dependencies_parsed_at":"2023-01-28T10:15:54.554Z","dependency_job_id":null,"html_url":"https://github.com/mint-dewit/media-conformer","commit_stats":null,"previous_names":["mint-dewit/media-conformer"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mint-dewit%2Fmedia-conformer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mint-dewit%2Fmedia-conformer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mint-dewit%2Fmedia-conformer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mint-dewit%2Fmedia-conformer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mint-dewit","download_url":"https://codeload.github.com/mint-dewit/media-conformer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250337638,"owners_count":21414097,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-02T08:57:39.232Z","updated_at":"2025-04-22T22:43:36.613Z","avatar_url":"https://github.com/mint-dewit.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# media-conformer\n\nThis project aims to make ffmpeg transcoding a drag and drop operation accessible by anyone, using presets built by with expert knowledge.\n\n![Media Conformer](https://raw.githubusercontent.com/baltedewit/media-conformer/master/images/media-conformer.png)\n\nThe following goals outline the project:\n\n- Drag and drop interface\n- Portable preset files\n- Batch processing\n- Automated 2 pass loudness processing\n- Gracefully handle interlaced conversion:\n  - interlaced to progressive\n  - progressive to interlaced\n  - field conversion (tff to bff and vice versa)\n\n## Acknowledgements\n\n- The ffmpeg project for making an amazing A/V tool free and open source.\n- Large bits around media processing were taken from nrkno/tv-automation-media-management\n- This project was generated using the vue-cli and vue electron cli plugin\n\n## Project setup\n\n```\nyarn install\n```\n\nNote: FFmpeg and FFprobe need to be in the PATH environment variable or you need to set a custom path in the application settings.\n\n### Compiles and hot-reloads for development\n\n```\nyarn electron:serve\n```\n\n### Compiles and minifies for production\n\n```\nyarn electron:build\n```\n\n### Lints and fixes files\n\n```\nyarn lint\n```\n\n## Preset files\n\n### Example file\n\n```jsonc\n{\n\t// Name of the preset to be shown in the settings:\n\t\"name\": \"Example Config\",\n\n\t// Analysis configuration\n\t\"blackFrames\": {},\n\t\"freezeFrames\": {},\n\t\"borders\": {},\n\t\"silence\": {},\n\t\"interlaced\": {},\n\t\"loudness\": true,\n\n\t// Per file, each encoder will spawn an ffmpeg process\n\t\"encoders\": [\n\t\t{\n\t\t\t\"postFix\": \"_YOUTUBE\",\n\t\t\t\"audioEncoder\": {},\n\t\t\t\"loudness\": {\n\t\t\t\t\"integrated\": -14\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"postFix\": \"_TV\",\n\t\t\t\"audioEncoder\": {},\n\t\t\t\"loudness\": {\n\t\t\t\t\"integrated\": -23\n\t\t\t},\n\t\t\t\"videoEncoder\": {},\n\t\t\t\"format\": {\n\t\t\t\t// having a format defined implies a reencode will be done\n\t\t\t\t\"width\": 1024\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"postFix\": \"_NO-AUDIO\",\n\t\t\t\"discard\": {\n\t\t\t\t\"audio\": true\n\t\t\t}\n\t\t}\n\t]\n}\n```\n\n### All options\n\nNote how a lot of times you can define an empty object, e.g. for the black frame analysis. Defining an empty object implies the ffmpeg defaults will be used.\n\n```ts\nexport interface Preset {\n\tname: string\n\n\t/** blackdetect filter */\n\tblackFrames?: {\n\t\tblackDuration?: number\n\t\tblackRatio?: number\n\t\tblackThreshold?: number\n\t}\n\t/** freezedetect filter (requires recent ffmpeg) */\n\tfreezeFrames?: {\n\t\tfreezeNoise?: number\n\t\tfreezeDuration?: number\n\t}\n\t/** cropdetect filter */\n\tborders?: {\n\t\tthreshold?: number\n\t\tround?: number\n\t\treset?: number\n\t}\n\t/** advanced interlace detection */\n\tinterlaced?: {\n\t\tanalyzeTime?: number\n\t}\n\t/** generate warnings for silence */\n\tsilence?: {\n\t\tnoise?: string\n\t\tduration?: string\n\t}\n\t/** enables 2-pass loudness correction */\n\tloudness?: boolean\n\n\tencoders: Array\u003cEncoderConfig\u003e\n}\n\nexport interface EncoderConfig {\n\t/** postfix to add to the filename */\n\tpostFix: string\n\t/** extension of the new file (e.g. .mp4) */\n\textension?: string\n\t/** custom options. Ignores all other options */\n\tcustom?: string\n\t/** discard streams */\n\tdiscard?: {\n\t\tvideo?: boolean\n\t\taudio?: boolean\n\t\tsubtitle?: boolean\n\t\tdata?: boolean\n\t}\n\t/** Configures loudnorm filter */\n\tloudness?: {\n\t\tintegrated?: number\n\t\ttruePeak?: number\n\t\tLRA?: number\n\t\tdualMono?: boolean\n\t}\n\t/** inserts scaler, rate conversion, interlacing/deinterlacing */\n\tformat?: {\n\t\twidth?: number\n\t\theight?: number\n\t\tframeRate?: number\n\t\taudioRate?: string\n\t\tinterlaced?: FieldOrder // possible values: tff or bff\n\t\tformat?: string // ffmpeg -f option\n\t\tcolorspace?: string\n\t}\n\t/** sets up the video encoder({} for default libx264, omit for copy) */\n\tvideoEncoder?: {\n\t\tencoder?: string\n\t\tencoderOptions?: Array\u003cstring\u003e\n\t}\n\t/** sets up the audio encoder ({} for default aac, omit for copy) */\n\taudioEncoder?: {\n\t\tencoder?: string\n\t\tencoderOptions?: Array\u003cstring\u003e\n\t}\n}\n```\n\n#### Custom encoder\n\nThe custom encoder enables the use of complex ffmpeg encoding/filter settings. It is assumed you know how to use ffmpeg when using the custom encoder.\n\nIt takes in a string of ffmpeg args and the output file path, name and extension are automatically appended.\n\n```json\n\"encoders\": [\n\t{\n\t\t\"postFix\": \"_custom-text-overlay\",\n\t\t\"extension\": \".mp4\",\n\t\t\"custom\": \"-vf drawtext=\\\"fontfile=/Windows/Fonts/arial.ttf: text='Custom text overlay': fontcolor=white: fontsize=120: box=1: boxcolor=black: boxborderw=20: x=(w-text_w)/2: y=(h-text_h)/1.4\\\"\"\n\t}\n]\n```\n\nThe custom encoder supports handlebar style string replacement for customising file names. If any handlebars are detected the output filename will not be automatically appended. You will need to handle the output file yourself (e.g. `{{dir}}/{{name}}{{postFix}}_Custom-format{{extension}}`).\n\n```json\n\"encoders\": [\n\t{\n\t\t\"postFix\": \"_Complex-Filter\",\n\t\t\"custom\": \"-an -filter_complex \\\"[0]pad=iw*2:ih[int];[int][0]overlay=W/2:0[doublewidth];[doublewidth]scale=iw/2:ih/2[scaled];[scaled]split=3[s1][s2][s3];[s1]crop=iw/3:ih:0:0[one];[s2]crop=iw/3:ih:ow:0[two];[s3]crop=iw/3:ih:ow*2:0[three]\\\" -map \\\"[one]\\\" -q:v 1 -sws_flags bicubic \\\"{{dir}}/{{name}}{{postFix}}_{{date}}_one{{ext}}\\\" -map \\\"[two]\\\" -q:v 1 -sws_flags bicubic \\\"{{dir}}/{{name}}{{postFix}}_{{date}}_two{{ext}}\\\" -map \\\"[three]\\\" -q:v 1 -sws_flags bicubic \\\"{{dir}}/{{name}}{{postFix}}_{{date}}_three{{ext}}\\\"\"\n\t}\n]\n```\n\nAvailable to use:\n\n```ts\npostFix     // EncoderConfig postfix\nextension?  // EncoderConfig extension\nroot        // Input file root name\ndir         // Input file directory\nbase        // Input file name with original extension\next         // Input file extension\nname        // Input file name\ndate        // Date in ISO format (YYYY-MM-DD)\n```\n\n# Contributors:\n\t- JonFranklin301\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmint-dewit%2Fmedia-conformer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmint-dewit%2Fmedia-conformer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmint-dewit%2Fmedia-conformer/lists"}