mirror of
https://github.com/amiaopensource/ffmprovisr.git
synced 2025-10-19 12:20:02 +02:00
Compare commits
30 Commits
v2019-11-0
...
v2020-05-1
Author | SHA1 | Date | |
---|---|---|---|
|
3984c8aae3 | ||
|
f9ef8dbae3 | ||
|
f814abbc0a | ||
|
843f05cc73 | ||
|
54577f4b28 | ||
|
aa5d63f4c4 | ||
|
dd257331fe | ||
|
feac0ded9b | ||
|
a33ed1d24f | ||
|
020b9fbe73 | ||
|
1df442f6dd | ||
|
3a05c8f440 | ||
|
89642fdd56 | ||
|
a9ec972aef | ||
|
91540a2fb8 | ||
|
2becad3d9c | ||
|
e4c327bbac | ||
|
4359d6dd4a | ||
|
d184ed2fe9 | ||
|
089725a753 | ||
|
897f1b1616 | ||
|
358a2ec23b | ||
|
de6c08a58d | ||
|
0d1fc1bfe8 | ||
|
cbca3ac7ad | ||
|
bcc425a955 | ||
|
0353c1761e | ||
|
e3aa81fb95 | ||
|
633374f22d | ||
|
1d60060eed |
71
index.html
71
index.html
@@ -2,11 +2,10 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>ffmprovisr</title>
|
||||
<meta name="viewport" charset="utf-8" content="text/html, width=device-width, initial-scale=1">
|
||||
<meta name="viewport" content="text/html, width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="css/css.css">
|
||||
<link rel="icon" href="img/vhs.ico">
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/js.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -18,7 +17,7 @@
|
||||
<nav class="sidebar well">
|
||||
<h2 class="heading">Table of Contents</h2>
|
||||
<a href="#about"><div class="contents-list">About this resource</div></a>
|
||||
<div id="open-all" class="contents-list">Show/hide all recipes</div>
|
||||
<div id="toggle-expand-collapse-all" class="contents-list">Expand/collapse all recipes</div>
|
||||
<a href="#basics"><div class="contents-list">FFmpeg basics</div></a>
|
||||
<a href="#concepts"><div class="contents-list">Advanced FFmpeg concepts</div></a>
|
||||
<a href="#rewrap"><div class="contents-list">Change container (rewrap)</div></a>
|
||||
@@ -124,6 +123,7 @@
|
||||
<li><code>.mxf</code>: Audio Codec: pcm_s16le, Video Codec: mpeg2video</li>
|
||||
<li><code>.wav</code>: Audio Codec: pcm_s16le (16 bit PCM)</li>
|
||||
</ul>
|
||||
<p class="link"></p>
|
||||
</div>
|
||||
<!-- End Codec Defaults -->
|
||||
|
||||
@@ -218,6 +218,36 @@
|
||||
</div>
|
||||
<!-- End Basic rewrap command -->
|
||||
|
||||
<!-- BWF -->
|
||||
<label class="recipe" for="bwf">Convert to (or create) Broadcast WAV</label>
|
||||
<input type="checkbox" id="bwf">
|
||||
<div class="hiding">
|
||||
<h5>Generate Broadcast WAV</h5>
|
||||
<p><code>ffmpeg -i <em>input_file.wav</em> -c copy -write_bext 1 -metadata field_name='Content' <em>output_file.wav</em></code></p>
|
||||
<p>This command will write a file in the Broadcast Wave Format (BWF) containing a BEXT chunk with related metadata.</p>
|
||||
<dl>
|
||||
<dt>ffmpeg</dt><dd>starts the command</dd>
|
||||
<dt>-i <em>input_file.wav</em></dt><dd>path and name of the input file</dd>
|
||||
<dt>-c copy</dt><dd>this will copy the encoding/sample rate etc from the input. If not using a WAV as the input file you will have to specify codec settings in place of this.</dd>
|
||||
<dt>-write_bext 1</dt><dd>tells FFmpeg to write a BEXT chunk, the part of the file where BWF metadata is stored.</dd>
|
||||
<dt>-metadata field_name='Content'</dt><dd>This is where you can specify which BEXT fields to write, and what information to fill them with by replacing <code>field_name</code> and <code>'Content'</code> respectively. See below for additional details.</dd>
|
||||
</dl>
|
||||
<p>Notes: You can choose which fields to write by repeating <code>-metadata field_name='Content'</code> for each desired field. Flags for commonly used fields (such as those recommended by the <a href="http://www.digitizationguidelines.gov/audio-visual/documents/Embed_Guideline_20120423.pdf">FADGI guidelines</a>) are as follows:</p>
|
||||
<ul>
|
||||
<li>description</li>
|
||||
<li>originator</li>
|
||||
<li>originator_reference</li>
|
||||
<li>origination_date</li>
|
||||
<li>origination_time</li>
|
||||
<li>coding_history</li>
|
||||
<li>IARL</li>
|
||||
</ul>
|
||||
<p>Example: <code>-metadata originator='US, UW Libraries'</code></p>
|
||||
<p>Additionally, users should be aware that BWF metadata fields are limited by characters, with some such as OriginatorReference maxing out at 32. Specific information can be found in the <a href="https://tech.ebu.ch/docs/tech/tech3285.pdf">Broadcast Wave Format specification</a>. Additional examples of BWF metadata usage can be found in the <a href="http://www.dlib.indiana.edu/projects/sounddirections/papersPresent/sd_bp_07.pdf">Sound Directions report</a> by Indiana University and Harvard.</p>
|
||||
<p class="link"></p>
|
||||
</div>
|
||||
<!-- ends BWF -->
|
||||
|
||||
<!-- Rewrap DV -->
|
||||
<label class="recipe" for="rewrap-dv">Rewrap DV video to .dv file</label>
|
||||
<input type="checkbox" id="rewrap-dv">
|
||||
@@ -245,7 +275,7 @@
|
||||
<input type="checkbox" id="to_prores">
|
||||
<div class="hiding">
|
||||
<h5>Transcode into a deinterlaced Apple ProRes LT</h5>
|
||||
<p><code>ffmpeg -i <em>input_file</em> -c:v prores -profile:v 1 -vf yadif -c:a pcm_s16le <em>output_file</em>.mov</code></p>
|
||||
<p><code>ffmpeg -i <em>input_file</em> -c:v prores -profile:v 1 -vf yadif -c:a pcm_s16le <em>output_file</em></code></p>
|
||||
<p>This command transcodes an input file into a deinterlaced Apple ProRes 422 LT file with 16-bit linear PCM encoded audio. The file is deinterlaced using the yadif filter (Yet Another De-Interlacing Filter).</p>
|
||||
<dl>
|
||||
<dt>ffmpeg</dt><dd>starts the command</dd>
|
||||
@@ -261,7 +291,7 @@
|
||||
<dt>-vf yadif</dt><dd>Runs a deinterlacing video filter (yet another deinterlacing filter) on the new file. <code>-vf</code> is an alias for <code>-filter:v</code>.</dd>
|
||||
<dt>-c:a pcm_s16le</dt><dd>tells FFmpeg to encode the audio stream in 16-bit linear PCM</dd>
|
||||
<dt><em>output_file</em></dt><dd>path, name and extension of the output file<br>
|
||||
The extension for the QuickTime container is <code>.mov</code>.</dd>
|
||||
There are currently three possible containers for ProRes 422 and 4444 which are all supported by FFmpeg: QuickTime (<code>.mov</code>), Matroska (<code>.mkv</code>) and Material eXchange Format (<code>.mxf</code>).</dd>
|
||||
</dl>
|
||||
<p>FFmpeg comes with more than one ProRes encoder:</p>
|
||||
<ul>
|
||||
@@ -698,6 +728,26 @@
|
||||
</div>
|
||||
<!-- ends Modify speed -->
|
||||
|
||||
<!-- Fade both video and audio streams -->
|
||||
<label class="recipe" for="fade_streams">Fade both video and audio streams</label>
|
||||
<input type="checkbox" id="fade_streams">
|
||||
<div class="hiding">
|
||||
<h5>Fade both video and audio streams</h5>
|
||||
<p><code>ffmpeg -i <em>input_file</em> -filter:v "fade=in:st=0:d=1, fade=out:st=59:d=1" -filter:a "afade=in:st=0:d=1, afade=out:st=59:d=1" -c:v libx264 -c:a aac <em>output_file</em></code></p>
|
||||
<p>This command fades in and out the first and last 30 video frames and 44100 audio samples on a video</p>
|
||||
<dl>
|
||||
<dt>ffmpeg</dt><dd>starts the command</dd>
|
||||
<dt>-i <em>input_file</em></dt><dd>path, name and extension of the input file</dd>
|
||||
<dt>-filter:v "fade=in:st=0:d=1, fade=out:st=59:d=1"</dt><dd>applies a video filter that fades in the first and last 30 video frames</dd>
|
||||
<dt>-filter:a "afade=in:st=0:d=1, afade=out:st=59:d=1"</dt><dd>applies an audio filter that fades in the first and last 30 video frames. <code>st</code> sets the start and <code>d</code> sets the duration.</dd>
|
||||
<dt>-c:v <em>video_codec</em></dt><dd>as a video filter is used, it is not possible to use <code>-c copy</code>. The video must be re-encoded with whatever video codec is chosen, e.g. <code>ffv1</code>, <code>v210</code> or <code>prores</code>.</dd>
|
||||
<dt>-c:a <em>audio_codec</em></dt><dd>as an audio filter is used, it is not possible to use <code>-c copy</code>. The audio must be re-encoded with whatever audio codec is chosen, e.g. <code>aac</code>.</dd>
|
||||
<dt><em>output_file</em></dt><dd>path, name and extension of the output_file</dd>
|
||||
</dl>
|
||||
<p class="link"></p>
|
||||
</div>
|
||||
<!-- ends Fade both video and audio streams -->
|
||||
|
||||
<!-- Synchronize video and audio streams -->
|
||||
<label class="recipe" for="sync_streams">Synchronize video and audio streams</label>
|
||||
<input type="checkbox" id="sync_streams">
|
||||
@@ -773,13 +823,13 @@
|
||||
<p>It's also possible to specify the crop position by adding the x and y coordinates representing the top left of your cropped area to your crop filter, as such:</p>
|
||||
<p><code>ffmpeg -i <em>input_file</em> -vf "crop=<em>width</em>:<em>height</em>[:<em>x_position</em>:<em>y_position</em>]" <em>output_file</em></code></p>
|
||||
<h5>Examples</h5>
|
||||
<p>The original frame, a screenshot of the SMPTE colorbars:</p>
|
||||
<p>The original frame, a screenshot of Maggie Cheung in the film <i>Hero</i>:</p>
|
||||
<img class="sample-image" src="img/crop_example_orig.png" alt="VLC screenshot of Maggie Cheung">
|
||||
<p>Result of the command <code>ffmpeg -i <em>smpte_colorsbars.mov</em> -vf "crop=500:500" <em>output_file</em></code>:</p>
|
||||
<p>Result of the command <code>ffmpeg -i <em>maggie.mov</em> -vf "crop=500:500" <em>output_file</em></code>:</p>
|
||||
<img class="sample-image-small" src="img/crop_example_aftercrop1.png" alt="VLC screenshot of Maggie Cheung, cropped from original">
|
||||
<p>Result of the command <code>ffmpeg -i <em>smpte_colorsbars.mov</em> -vf "crop=500:500:0:0" <em>output_file</em></code>, appending <code>:0:0</code> to crop from the top left corner:</p>
|
||||
<p>Result of the command <code>ffmpeg -i <em>maggie.mov</em> -vf "crop=500:500:0:0" <em>output_file</em></code>, appending <code>:0:0</code> to crop from the top left corner:</p>
|
||||
<img class="sample-image-small" src="img/crop_example_aftercrop2.png" alt="VLC screenshot of Maggie Cheung, cropped from original">
|
||||
<p>Result of the command <code>ffmpeg -i <em>smpte_colousbars.mov</em> -vf "crop=500:300:500:30" <em>output_file</em></code>:</p>
|
||||
<p>Result of the command <code>ffmpeg -i <em>maggie.mov</em> -vf "crop=500:300:500:30" <em>output_file</em></code>:</p>
|
||||
<img class="sample-image-small" src="img/crop_example_aftercrop3.png" alt="VLC screenshot of Maggie Cheung, cropped from original">
|
||||
<p class="link"></p>
|
||||
</div>
|
||||
@@ -2812,5 +2862,6 @@ Change the above data-target field, the hover-over description, the button text,
|
||||
<p>Made with ♥ at <a href="https://wiki.curatecamp.org/index.php/Association_of_Moving_Image_Archivists_%26_Digital_Library_Federation_Hack_Day_2015" target="_blank">AMIA #AVhack15</a>! Contribute to the project via <a href="https://github.com/amiaopensource/ffmprovisr" target="_blank">our GitHub page</a>!</p>
|
||||
</footer>
|
||||
</div><!-- ends "grid" -->
|
||||
<script src="js/js.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
4
js/jquery.min.js
vendored
4
js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
126
js/js.js
126
js/js.js
@@ -1,42 +1,96 @@
|
||||
$(document).ready(function() {
|
||||
function scrollTo(element, to, duration) {
|
||||
var start = element.scrollTop,
|
||||
change = to - start,
|
||||
currentTime = 0,
|
||||
increment = 20;
|
||||
|
||||
function appendLink(id) {
|
||||
$(id).next('div').find('.link').empty();
|
||||
$(id).next('div').find('.link').append("<small>Link to this command: <a href='https://amiaopensource.github.io/ffmprovisr/index.html" + id + "'>https://amiaopensource.github.io/ffmprovisr/index.html" + id + "</a></small>");
|
||||
}
|
||||
|
||||
function moveToRecipe(id) {
|
||||
document.getElementById(id.substring(1)).checked = true;
|
||||
$('html, body').animate({ scrollTop: $(id).offset().top }, 1000);
|
||||
appendLink(id)
|
||||
}
|
||||
|
||||
// open recipe window if a hash is found in URL
|
||||
if (window.location.hash) {
|
||||
id = window.location.hash
|
||||
moveToRecipe(id)
|
||||
}
|
||||
|
||||
// add hash URL when recipe is opened
|
||||
$('label[class="recipe"]').on("click", function(){
|
||||
id = $(this).attr("for");
|
||||
window.location.hash = ('#' + id)
|
||||
appendLink('#' + id)
|
||||
})
|
||||
|
||||
// open recipe when clicked
|
||||
$('a').on("click", function(){
|
||||
intralink = $(this).attr("href")
|
||||
if (intralink[0] == "#") {
|
||||
moveToRecipe(intralink)
|
||||
var animateScroll = function(){
|
||||
currentTime += increment;
|
||||
var val = Math.easeInOutQuad(currentTime, start, change, duration);
|
||||
element.scrollTop = val;
|
||||
if(currentTime < duration) {
|
||||
setTimeout(animateScroll, increment);
|
||||
}
|
||||
}
|
||||
animateScroll()
|
||||
}
|
||||
|
||||
//t = current time, b = start value, c = change in value, d = duration
|
||||
Math.easeInOutQuad = function (t, b, c, d) {
|
||||
t /= d/2;
|
||||
if (t < 1) return c/2*t*t + b;
|
||||
t--;
|
||||
return -c/2 * (t*(t-2) - 1) + b;
|
||||
}
|
||||
|
||||
function appendLink(id) {
|
||||
const link = document.getElementById(id).nextElementSibling.querySelector('.link')
|
||||
if (link) {
|
||||
link.innerHTML = ("<small>Link to this command: <a href='https://amiaopensource.github.io/ffmprovisr/index.html#" + id + "'>https://amiaopensource.github.io/ffmprovisr/index.html#" + id + "</a></small>")
|
||||
}
|
||||
}
|
||||
|
||||
function moveToRecipe(id) {
|
||||
document.getElementById(id).checked = true;
|
||||
scrollTo(document.body, 0, 1000);
|
||||
appendLink(id)
|
||||
}
|
||||
|
||||
// open recipe window if a hash is found in URL
|
||||
if (window.location.hash) {
|
||||
id = window.location.hash.slice(1)
|
||||
moveToRecipe(id)
|
||||
}
|
||||
|
||||
// add hash URL when recipe is opened
|
||||
const recipes = document.querySelectorAll('label[class="recipe"]')
|
||||
recipes.forEach(function(item, i){
|
||||
item.addEventListener("click", function(){
|
||||
id = this.getAttribute("for");
|
||||
window.location.hash = (id)
|
||||
appendLink(id)
|
||||
})
|
||||
})
|
||||
|
||||
// open all windows if button is clicked
|
||||
$('#open-all').on("click", function(){
|
||||
$('input[type=checkbox]').each(function(){
|
||||
this.checked = !this.checked;
|
||||
|
||||
// open recipe when clicked
|
||||
const links = document.querySelectorAll('a')
|
||||
links.forEach(function(item, i){
|
||||
|
||||
item.addEventListener("click", function(){
|
||||
intralink = this.getAttribute("href")
|
||||
if (intralink[0] == "#") {
|
||||
moveToRecipe(intralink.substring(1))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
function getCheckedBoxes(checkboxes) {
|
||||
var checkboxesChecked = [];
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].checked) {
|
||||
checkboxesChecked.push(checkboxes[i]);
|
||||
}
|
||||
}
|
||||
return checkboxesChecked.length > 0 ? checkboxesChecked : null;
|
||||
}
|
||||
|
||||
// Collapse all recipes when button is clicked
|
||||
document.getElementById('toggle-expand-collapse-all').addEventListener("click", function(){
|
||||
const checkboxes = document.querySelectorAll('input[type=checkbox]')
|
||||
var checked = getCheckedBoxes(checkboxes);
|
||||
|
||||
if (checked) {
|
||||
// Collapse all
|
||||
document.querySelectorAll('input[type=checkbox]').forEach(function(item, i){
|
||||
item.checked = false;
|
||||
})
|
||||
} else {
|
||||
// Expand all
|
||||
document.querySelectorAll('input[type=checkbox]').forEach(function(item, i){
|
||||
item.checked = true;
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
});
|
||||
|
26
readme.md
26
readme.md
@@ -10,7 +10,7 @@ Repository of useful FFmpeg command lines for archivists!
|
||||
* [Contributors](#contributors)
|
||||
* [AVHack Team](#avhack-team)
|
||||
* [Sister projects](#sister-projects)
|
||||
* [Awards and mentions](#articles-and-mentions)
|
||||
* [Articles and mentions](#articles-and-mentions)
|
||||
* [License](#license)
|
||||
|
||||
## What is this?
|
||||
@@ -83,31 +83,36 @@ You can read our contributor code of conduct [here](https://github.com/amiaopens
|
||||
|
||||
*Code Contributors*:
|
||||
ablwr (Ashley)
|
||||
alavigne12 (A. Lavigne)
|
||||
Anushka-codergirl (Anushka Raj)
|
||||
bastibeckr (Basti Becker)
|
||||
b00giehead (Joanna White)
|
||||
bturkus
|
||||
dericed (Dave Rice)
|
||||
digitensions (Joanna White)
|
||||
edsu (Ed Summers)
|
||||
jamessam (Jim Sam)
|
||||
jfarbowitz (Jonathan Farbowitz)
|
||||
kfrn (Katherine Frances Nagels)
|
||||
kgrons (Kathryn Gronsbell)
|
||||
kieranjol (Kieran O'Leary)
|
||||
llogan (Lou)
|
||||
llogan (Lou Logan)
|
||||
macasaurusrex (Maura)
|
||||
mgiraldo (Mauricio Giraldo)
|
||||
pjotrek-b (Peter B.)
|
||||
privatezero (Andrew Weaver)
|
||||
retokromer (Reto Kromer)
|
||||
rfraimow
|
||||
|
||||
*All Contributors*:
|
||||
All Contributors:
|
||||
ablwr (Ashley)
|
||||
alavigne12 (A. Lavigne)
|
||||
Anushka-codergirl (Anushka Raj)
|
||||
audiovisualopen
|
||||
bastibeckr (Basti Becker)
|
||||
b00giehead (Joanna White)
|
||||
brainwane (Sumana Harihareswara)
|
||||
bturkus
|
||||
dericed (Dave Rice)
|
||||
digitensions (Joanna White)
|
||||
drodz11 (Dave Rodriguez)
|
||||
edsu (Ed Summers)
|
||||
EG-tech (Ethan Gates)
|
||||
@@ -122,7 +127,9 @@ kellyhaydon (metacynic)
|
||||
kfrn (Katherine Frances Nagels)
|
||||
kgrons (Kathryn Gronsbell)
|
||||
kieranjol (Kieran O'Leary)
|
||||
llogan (Lou)
|
||||
llogan (Lou Logan)
|
||||
macasaurusrex (Maura)
|
||||
mercuryswitch
|
||||
mgiraldo (Mauricio Giraldo)
|
||||
mulvya
|
||||
nkrabben (Nick Krabbenhoeft)
|
||||
@@ -132,12 +139,13 @@ retokromer (Reto Kromer)
|
||||
rfraimow
|
||||
richardpl (Paul B Mahol)
|
||||
ross-spencer (Ross Spencer)
|
||||
taschenbach (Tommy Aschenbach)
|
||||
todrobbins (Tod Robbins)
|
||||
|
||||
Repo: amiaopensource/ffmprovisr
|
||||
Code Contributors: 17
|
||||
All Contributors: 32
|
||||
Last updated: 2019-02-11
|
||||
GitHub Contributors: 20
|
||||
All Contributors: 37
|
||||
Last updated: 2019-12-11
|
||||
|
||||
## AVHack Team
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
# Basic rewrap command
|
||||
ffmpeg -i input_file.ext -c copy -map 0 output_file.ext
|
||||
# Generate Broadcast WAV
|
||||
ffmpeg -i input_file.wav -c copy -write_bext 1 -metadata field_name='Content' output_file.wav
|
||||
# Rewrap DV video to .dv file
|
||||
ffmpeg -i input_file -f rawvideo -c:v copy output_file.dv
|
||||
# Transcode to deinterlaced Apple ProRes LT
|
||||
@@ -36,6 +38,8 @@ ffmpeg -i input_file -c:v copy -aspect 4:3 output_file
|
||||
ffmpeg -i input_file -c:v libx264 -vf colormatrix=src:dst output_file
|
||||
# Modify image and sound speed
|
||||
ffmpeg -i input_file -r output_fps -filter_complex "[0:v]setpts=input_fps/output_fps*PTS[v]; [0:a]atempo=output_fps/input_fps[a]" -map "[v]" -map "[a]" output_file
|
||||
# Fade both video and audio streams
|
||||
ffmpeg -i input_file -filter:v "fade=in:st=0:d=1, fade=out:st=59:d=1" -filter:a "afade=in:st=0:d=1, afade=out:st=59:d=1" -c:v libx264 -c:a aac output_file
|
||||
# Synchronize video and audio streams
|
||||
ffmpeg -i input_file -itsoffset 0.125 -i input_file -map 1:v -map 0:a -c copy output_file
|
||||
# Clarify stream properties
|
||||
|
Reference in New Issue
Block a user